Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Comment: | Converted TIPs to Markdown |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA3-256: |
9f0c27f8d14faef5e50a194ccd93f0f5 |
User & Date: | mjanssen 2017-09-06 14:15:49 |
2017-09-06
| ||
14:15 | Added script to generate index check-in: e62d322a99 user: mjanssen tags: trunk | |
14:15 | Converted TIPs to Markdown check-in: 9f0c27f8d1 user: mjanssen tags: trunk | |
14:15 | Clean-up CVS import check-in: dce4aef4b9 user: mjanssen tags: trunk | |
Name change from tip/0.tip to tip/0.md.
|
| < | < | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 276 277 278 279 280 281 282 283 284 285 286 287 288 | # TIP 0: Tcl Core Team Basic Rules Author: John Ousterhout <[email protected]> State: Final Type: Process Vote: Done Created: 11-Dec-2000 Post-History: ----- # Abstract This TIP describes the mission, structure, and operating procedures of the Tcl Core Team \(TCT\). When in doubt about how the TCT works, consult this document as the final authority. # Introduction The Tcl Core Team is a self-organizing group of Tcl experts who are responsible for the evolution and management of the Tcl core. The Tcl Core Team decides what goes into releases; it implements, tests, and documents new features and bug fixes; it manages the release process; and it also manages the Tcl Developer Exchange Web site. # Scope: the Tcl core The phrase "Tcl core" refers to the Tcl interpreter and the Tk toolkit \(the packages previously released by Sun, Scriptics, and Ajuba\). We also include the Tcl Developer Exchange Web site and the Tcl bug database in the Tcl core. The Tcl Core Team may also choose to take on additional responsibilities such as the creation of more comprehensive "batteries included" releases. We expect other Tcl development teams to form independently from the Tcl Core Team to manage additional projects, such as popular extensions. The Tcl Core Team may eventually spin off some of its activities into separate teams. # Team membership The Tcl Core Team is a small group of people who are making major contributions to the development of the Tcl core and who are highly respected and trusted by the Tcl community. Team members are expected to invest significant amounts of their time to improve the Tcl core. The original group of Team members was elected by the Tcl community, but the TCT now handles its own membership according to rules described here. To become a member of the Team you must be nominated by an existing member and voted on by the existing Team; you must receive 2/3 of the votes cast. If you would like to join the Tcl Core Team, you should first demonstrate your development skills and leadership by participating in development projects under the auspices of an existing team member. Inactive or disruptive members of the team can be removed by a vote of other Team members: a 2/3 majority of those voting is required to remove a Team member. # Communication The primary mechanism for communicating with the Tcl Core Team is the mail alias [email protected]. This is a public mailing list; anyone interested in following the discussions of the TCT is welcome to join the mailing list. Email sent to this alias is archived, so you can review previous discussions at SourceForge. # Basic organizational structure The team structure is simple and flat. All members have equal standing: there is no Chairman. The Tcl Core Team makes its own rules and chooses its own members as described in this document. Anyone on the Tcl Core Team can propose a change in the rules; after discussion, the change is voted on by the Team and must receive 2/3 of the votes cast. The person proposing a rules change is responsible for making sure that the change is properly implemented after it has been approved \(e.g. by modifying this TIP, creating additional tools, etc.\). # 2/3 vote Wherever a 2/3 vote is called for in this document, it means that a proposal must receive _at least two-thirds of the votes cast_, not votes from at least two-thirds of all TCT members. # Projects and maintainers Tcl improvements are organized around two key ideas: _projects_ and _maintainers_. Most of the activities of the Tcl Core Team consist of projects. A project can consist of a bug fix, a new feature in the Tcl core, a new facility in the Tcl Developer Exchange, or anything else except a change to this TIP. We divide projects into two general categories: bug fixes and feature changes. In general, if a project requires manual entries to be updated then it is a feature change; when in doubt, a project is a feature change . Bug fixes use a more streamlined process for implementation, whereas feature changes require discussion and approval in advance. A maintainer is someone who has taken primary responsibility for a portion of the Tcl sources. Many maintainers will be members of the Tcl Core Team, but the Team may also select maintainers from outside the Tcl Core Team. We hope to find enough maintainers to cover all of the Tcl sources, but we will appoint a _default maintainer_ to handle the parts of Tcl for which no other maintainer has volunteered. We'll also try to have backup maintainers who can step in when the primary maintainers are on vacation or otherwise unavailable. A maintainer accepts several responsibilities, including the following: * Monitoring the bug database for bugs in his/her area. * Arranging for bugs to be fixed, either by doing it himself/herself or finding someone else to do it. * Coordinating and reviewing all modifications to his/her area. * Providing assistance to other people working in his/her area. # Project life-cycle: approval, implementation, integration; TYANNOTT The project for a feature change goes through three stages: approval, implementation, and integration. A project starts when a member of the Tcl Core Team proposes it to the Team. Proposals are submitted by emailing TIPs \(Tcl Improvement Proposals\) to the Tcl Core Team. The format of TIPs is described in a separate TIP. Whoever proposes a project is responsible for making sure it is properly implemented. A proposal without a committed implementor cannot be approved. Project approval is done through a process called _TYANNOTT_: Two Yesses And No No's Or Two Thirds. In order for a project to be approved it must have support from at least one other member of the Tcl Core Team besides the proposer. Once a project has been proposed and discussed, if there are no objections and there is a vote of confidence from a second team member \("Two Yesses And No No's"\), then the project is approved. If objections remain after the discussion, then the proposer must summarize the objections and call for a vote of the TCT; a 2/3 vote is required for approval. The idea here is that most projects will be no-brainers and we want a simple decision process that doesn't get in the way of progress. On the other hand, the Tcl Core Team can only work effectively if it is highly collegial; if the Team can't reach pretty clear agreement on a project \(i.e more than 1/3 of the TCT objects to it\) then the project needs to be rethought. The second phase of a project is implementation. The proposer is responsible for the implementation, either doing it himself/herself or arranging for someone else to do it. The implementation is done in a private work area and may not be integrated with the official sources until the third phase, below. The third phase of a project is integrating the results back into the official Tcl repository. This is where maintainers come in. First, before any change can be applied to the official Tcl sources, the implementor must post it as a patch to the SourceForge patch manager. This rule applies regardless of the type of change \(anything from a 1-line bug fix to a major new feature\) and regardless of who is proposing the change. We use the SourceForge patch manager to record all changes and also to facilitate discussion about the changes before they are applied. When a patch arrives in the SourceForge patch manager, the appropriate maintainer reviews it and works with the proposer to revise it as necessary. Other people can also review the patch, since it is public. If changes are needed, a revised patch is logged in the patch manager \(the final version of the patch must always appear in the SourceForge patch manager\). Once the maintainer is satisfied with the patch, it can be applied to the Tcl sources. If the patch implementor has write access to the sources that he or she can apply the patch once the maintainer has approved it. If the patch implementor doesn't have write access to the sources than the maintainer applies the patch. Maintainers are responsible for watching the SourceForge patch manager to make sure that incoming patches in their area are dealt with quickly. If the implementor of a patch is the maintainer, then he/she can apply the patch to the Tcl sources immediately after logging it in the SourceForge patch manager, without waiting for additional approval. However, if someone objects to the patch then the maintainer must be prepared to revise it after the fact. # Fast path for bug fixes For a bug fix, no initial proposal or approval is required. The only approval needed is for the maintainer to review the patch before it is applied to the sources. For example, we invite everyone in the Tcl community to fix bugs and submit patches to the SourceForge patch manager. # Implementors outside the Tcl Core Team We encourage people outside the Tcl Core Team to get involved with Tcl development. For example, anyone can submit patches for bug fixes. It's also fine for someone outside the Tcl core team to propose a feature change and then implement it, but there must be a sponsor on the Tcl Core Team who will take personal responsibility for it. Typically the sponsor will be the maintainer for the area of the change. It is the sponsor's responsibility to provide whatever level of supervision is appropriate to ensure that the project is executed well. If the implementor for a project is not a TCT member then they cannot vote for approval: TYANNOTT requires the sponsor plus one other Team member. # Raising concerns If you have concerns about a project, the best time to raise them is during the initial discussion. Once a project has been approved, the best approach is to raise the issue directly with the implementor; most issues should get resolved quickly this way. If you can't find the implementor or can't reach agreement, and if the implementor is not a member of the Tcl Core Team, the next person to talk to is the Tcl Core Team member in charge of the project. If you still can't get satisfaction, then raise the issue with the entire Tcl Core Team by leading a discussion. Once all the issues are out, you can either withdraw your objection or summarize the issues \(on both sides!\) and call for a vote. If you aren't a member of the Tcl Core Team you will need to convince a Team member to manage the discussion and vote. Even if a project has received initial approval, a Team member can object to the project later \(e.g. if they believe it hasn't been implemented properly\). If the objection isn't resolved there will be an additional vote of the Team, and the project cannot be applied to the official sources unless it receives a 2/3 majority of the votes cast. At the same time, Team members are expected to raise their objections as early as possible; it would be somewhat anti-social to raise a basic design objection late in the implementation of a project when it could have been raised during the initial approval. # Disagreements over patches Normally, patches are not reviewed by the entire TCT; once the relevant maintainer has reviewed and approved them then they can be integrated. However, everyone is invited to review as many patches as they wish. If someone on the TCT objects to a patch and can't resolve the objection with the implementor and/or maintainer, then it gets discussed by the entire Tcl Core Team with the usual rules: if anyone on the Tcl Core Team has an objection that isn't resolved by the discussion, then a 2/3 vote is required to retain the patch. Thus if an implementor reaches a disagreement with a maintainer he/she can appeal to the entire Tcl Core Team. Or, if someone on the Tcl Core Team objects to a patch applied by a maintainer, they too can start a discussion in the whole team. The goal of the maintainer mechanism is to simplify and speed up improvements in the common case where everyone is in agreement, while still allowing the entire Tcl Core Team to offer input and resolve disagreements. # Changes that span areas If a change involves several different areas of the Tcl sources, with different maintainers, then one of the maintainers acts as coordinator \(presumably the one whose area has the most changes\). It is their responsibility to consult with other maintainers whose areas are affected, so that all relevant maintainers are happy before the patch is applied to the sources. # Write access to the Tcl sources and the Web site Everyone in the Tcl Core Team has write access to all the sources and the Web site, but they may only make changes consistent with approved projects. The Tcl Core Team can also give access to other people who are working on projects. For example, as part of a project proposal a Tcl Core Team member can propose that the work will be done by someone outside the team, and that that person should have write access for putting back changes. Giving out write access is part of a project decision, with the associated rules for approval. However, if someone outside the Tcl Core Team has write access, it must be under the auspices of a Tcl Core Team member; the Tcl Core Team member is personally responsible for making sure the project is completed satisfactorily and/or cleaning up any messes. # Deadlock resolution If something should go wrong with the TCT organization and the Tcl Core Team deadlocks to a point where it can't make meaningful progress, then John Ousterhout will step in as benevolent dictator and make enough unilateral decisions to break the deadlock. # Copyright This document has been placed in the public domain. |
Name change from tip/1.tip to tip/1.md.
|
| < | < | | | | | | > | | | | | | | | > | 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 | # TIP 1: TIP Index Author: TIP Editor <[email protected]> State: Active Type: Informational Vote: No voting Created: 14-Sep-2000 Post-History: ----- # Abstract This TIP contains the index of all TIPs published over the lifetime of the TCT. It will be continually and automatically updated. # Index \#index: White backgrounds indicate that the TIP is still a draft, yellow backgrounds highlight TIPs being voted on, and where a TIP has been rejected, withdrawn or obsoleted its index entry has a dark grey background. Blue backgrounds indicate a TIP has been accepted, but still needs an implementation approved by maintainers. Green backgrounds indicate that the TIP is deferred, waiting for someone to work on it. # Explanations and How To Submit New TIPs See [[2]](2.md) for a description of the editorial process a TIP has to go through and [[3]](3.md) for a description of their structure and the commands used to write them. You submit a TIP to this archive by emailing it \(preferably in source form\) to the TIP editor <[email protected]> who will check it for following of the guidelines, style and general relevance to Tcl/Tk before checking it into the CVS archive and notifying the author, the rest of the Tcl Core Team, and the relevant newsgroups. # Copyright This document has been placed in the public domain. |
Name change from tip/10.tip to tip/10.md.
|
| < | < | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 10: Tcl I/O Enhancement: Thread-Aware Channels Author: Andreas Kupries <[email protected]> State: Final Type: Project Vote: Done Created: 08-Nov-2000 Post-History: Tcl-Version: 8.4 ----- # Abstract This TIP describes how to change the generic I/O layer in the Tcl core to make channels aware of the thread they are managed by. # Rationale To explain the motives behind this TIP first a short look at the history of channels and threading. In ancient times the Tcl core was not thread safe and did not employ threads. All channels belonged to a single interpreter. Later on interpreter hierarchies were introduced and the ability to move or share a channel between the interpreters in a hierarchy. When the Tcl core was made thread safe a short time after the ability to move channels between threads was added \(Helper APIs in the core, main functionality in the Thread extension\). The goal behind these modifications was to enable the creation of stream-like communication paths between threads to complement the message based facilities \(thread send\). The modifications were only a partial success because an in-depth analysis of the relevant data structures showed that the sharing of a channel between threads is not possible with the current design, only moving. This was implemented to allow at least the dispatcher- / worker-thread pattern for structuring a threaded application. In further pursuit of the original goal the currently chosen approach is to define a channeltype where two channels are connected internally through in-memory fifo buffers where access to these shared structures is protected by mutexes. During the implementation of fileevents for this channeltype it was discovered that an efficient implementation of this part is _not_ possible because of the inability to post file events to the eventqueue of the thread the other channel of the pair resides in. An API to post such events is available \(_Tcl\_ThreadQueueEvent_\), but not the information which thread actually manages the other channel. Because of this the current implementation of the channeltype uses polling based upon timer events posted by each side/thread to itself to manage file events in a rather inefficient way. # Reference implementation This TIP now proposes to change the internals of the generic I/O layers in the core so that 1. Channels know the thread they are managed by, and 1. are able to deliver this information to an extension querying the core. This then allows the two sides of the channeltype mentioned above to post events to each other, facilitating an efficient implementation of fileevents. The changes necessary to accomplish this are: 1. Extend the structure _ChannelState_ in tclIO.h with a new field of type _Tcl\_ThreadId_ to hold the id of the thread currently managing all channels with this state. Note: This structure is shared by all channels in a stack of transformations. 1. Modify the procedure _Tcl\_CreateChannel_ to store the Id of the current thread in the _ChannelState_ of the new channel. This information can be obtained with _Tcl\_GetCurrentThread_. It is _not_ necessary to modify _Tcl\_StackChannel_ as the thread information is already part of the state when it is called, and won't be changed by the call. 1. If some sort of NIL/NULL value meaning "No thread" is available for _Tcl\_ThreadId_, then we should modify _Tcl\_CutChannel_ to insert this value into the state of the channel it is called with, as this channel will not be managed by any thread afterward \(the procedure removes the channel from the list of all channels managed by the current thread\). 1. Modify _Tcl\_SpliceChannel_ in the same manner as _Tcl\_CreateChannel_ as the channel will be managed by the current thread afterward \(The procedure adds the channel to the list of all channels managed by the current thread\). 1. Declare a new API function to retrieve the Id of the managing thread from a channel. Add this declaration to generic/tcl.decls and implement the function in the file generic/tclIO.c. I propose _Tcl\_GetChannelThread_ as the name of this new API function. A patch implementing all of the changes described above and additionally extending the documentation and the test-suite is available here: <http://www.cs.man.ac.uk/fellowsd-bin/TIP/10.patch> # Copyright This document has been placed in the public domain. |
Name change from tip/100.tip to tip/100.md.
|
| < | < | | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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 | # TIP 100: Add Support for Unloading Dynamic Libraries Loaded with [load] Author: George Petasis <[email protected]> State: Final Type: Project Vote: Done Created: 11-Jun-2002 Post-History: Discussions-To: news:comp.lang.tcl Keywords: load,unload,dynamic library Tcl-Version: 8.5 ----- # Abstract Tcl already provides facilities for loading dynamic libraries, through the _load_ command. However no facilities are currently offered in order to _unload_ dynamic libraries already loaded with the _load_ command. This TIP tries to add support for unloading libraries, by introducing a new Tcl command \(_unload_\) and the guidelines that dynamic libraries must follow, in order to be unloadable. Note that the _unload_ command will operate only on libraries that are designed to be unloadable by their developers. This way backward compatibility with older extensions is maintained, as unload will never try to unload libraries unaware of this new functionality. # Rationale Tcl is an ideal language for component-based applications. Usually these applications offer a framework in which components developed by the users of the application can be embedded, in order to extend the functionality of the framework. Usually, these extensions are implemented as C/C\+\+ dynamic libraries that are loaded through the _load_ Tcl command. However the development of such components can be a time-consuming process, as developers have to restart the framework application in order to be able to reload the library into it and test its altered functionality. And this can be quite annoying \(depending on the application of course\), as usually processing within the application is required in order to bring it into a proper state before testing the library. The development cycle can be significantly shortened if Tcl provides a mechanism for unloading a dynamic library. A new version of the library can be created, as its object file can now be written, and the updated library can be re-loaded. However, this is not the only application of unload. Services running for long periods of time and want to unload no longer needed functionality, replacing parts of an applications \(i.e. from an automatic update procedure\) or functionality temporarily needed \(i.e. a web browser that loads a plugin to display a file of a particular file type\) are some additional fields of application. # Introduction Unload functionality has been left out of the Tcl core, mainly because library unloading was poorly implemented in many operating systems. But almost all operating systems have been improved in the meantime, and as a result most modern operating systems now support library unloading. The main idea of this TIP is to enable dynamic library unloading at the Tcl level, in the same sense _load_ provides dynamic library loading. However, library unloading will be provided only when the underlying operating system support this feature \(as is also the case for _load_\) and only when the library to be unloaded provides a set of functions that can "undo" the changes the library has made to the interpreter. In all other cases, unloading a library will result in an error. This TIP proposes the insertion of a new Tcl command named _unload_ and two functions _pkg\_Unload_ and _pkg\_SafeUnload_, modelled after _pkg\_Init_ and _pkg\_SafeInit_, that libraries which can be unloaded should implement. # Unloadable Libraries A main concern is related to when a shared library can be "unloadable". An unloadable library is a library characterised as such by its developer. The developer of the library must export a function from the library, similar to the library's initialisation function. The unload command will never try to unload a library that does not provide such a function. This makes old libraries \(before the introduction of the unload functionality\) safe. There is a category of libraries that can never be unloaded \(i.e. libraries that register new tcl object types\). However, the choice is upon the developer: the developer knows if the library can be unloadable. The simpler case, libraries that only register new commands are the most probable libraries to be unloadable. Libraries that export functions through a stub mechanism cannot be unloaded, as the were meant for having dependencies with other libraries that use the exported API. There is no way for the provider library to know wether it is used or not. # Specification Actually, all the facilities for unloading dynamic libraries already exist in the Tcl core and simply they are not yet exposed at the Tcl level. As a result, the implementation of the unload command should be fairly easy. _load_ as it is currently implemented loads a dynamic library only the first time this library is loaded. It keeps an internal cache of all loaded libraries and if an already loaded library is requested again, only its initialisation function is called. This cache should be extended to keep some additional information: 1. Two reference counts, counting how many times a specific library has been loaded. This reference count should be increased by each _load_ and decreased for each _unload_. When it reaches 0, the library can be unloaded. Safe interpreters and normal interpreters should have different reference counts. Both should be 0 in order for a library to be unloaded. 2. The addresses of the _pkg\_Unload_ and _pkg\_SafeUnload_ functions, if these are implemented by the library. If both of these functions are missing, the library will never be unloaded. If only _pkg\_Unload_ is implemented, the library can be unloaded if it never has been loaded in a safe interpreter. Finally, if _pkg\_SafeUnload_ is implemented, the library can be unloaded if it has never been loaded in a normal interpreter. The _unload_ command will always return an error, if the operating system does not support library unloading. In case the operating system supports library unloading: 1. _unload_ will examine the cache of _load_ to locate the entry for the library to be unloaded. It is an error to unload a library that has not been loaded with _load_. 2. If the entry in the cache is found, _unload_ checks whether the corresponding for the interpreter type unload function pointer is NULL or not. If it is NULL, the library cannot be unloaded under this interpreter and again an error is returned. 3. If the unload function pointer is not NULL, it is executed. If an error is returned by this function, _unload_ also returns an error. 4. If the unload function finishes without errors, the reference count corresponding to the interpreter type is decreased. If both reference counts reach 0, the library is unloaded. # Responsibilities of the Unload Functions Its up to the developer of the library to decide if its library can be unloaded or not. A library can be unloaded if the function _pkg\_Unload_ is implemented and exported as a symbol from the library, and the library will never be loaded in a safe interpreter. A library that can be also loaded in safe interpreters is unloadable if the function _pkg\_SafeUnload_ is also available. These two functions will accept two arguments, the interpreter under which the library is unloaded and an integer, holding various flags. The flags argument can be either _TCL\_UNLOAD\_DETACH\_FROM\_INTERPRETER_ or _TCL\_UNLOAD\_DETACH\_FROM\_PROCESS_. In case the library will remain attached to the process after the unload procedure returns \(i.e. because the library is used by other interpreters\), TCL\_UNLOAD\_DETACH\_FROM\_INTERPRETER will be defined. However, if the library is used only by the target interpreter and the library will be detached from the application as soon as the unload procedure returns, the flags argument will be set to TCL\_UNLOAD\_DETACH\_FROM\_PROCESS. The main responsibility of these functions is to remove from the interpreter they are unloaded under any reference to a function residing inside the library. For example, such a function must: 1. Unregister any commands that have been registered by the _Init\(\)_ function to the _interpreter_ given by the first argument. In order to do this, the library should keep internally the tokens returned by each _Tcl\_Create\*Command_, as command may have been renamed. 2. Unregister any other commands that may have been registered to the interpreter during the use of the library \(usually used to represent special special data structures\). If the flag _TCL\_UNLOAD\_DETACH\_FROM\_PROCESS_ is defined, the developer must do additional task, that are not normally required when the library gets unloaded from an interpreter: 3. Free any memory occupied by the internal structures of the library. 4. In general, try to remove any references Tcl may have to functions provided by the library. If the developer cannot remove all reference to functions to the library, its better to not provide at all these two functions, so as unload to never attempt to unload the library. # Dependencies Among Libraries It is possible that a library A has been loaded that exports some symbols. Then a library B is loaded, that has dependencies \(i.e. uses some exported symbols\) on A. What if A gets unloaded? Actually, most modern operating systems seem to provide a solution to this problem, as reference counts are hold internally by the operating system for each library. Newer Windows, Solaris and Linux seem to provide similar solutions and in reality they don't unload the library if such symbols remain, even if the unload system call has been made for the library. Both libraries A and B have to be unloaded in order for A to be really removed from the address space. # Reference Implementation A reference implementation can be found at: <http://sf.net/tracker/?func=detail&aid=823486&group\_id=10894&atid=310894> # Copyright This document has been placed in the public domain. # Appendix: The unload man page. NAME unload - Unload machine code. SYNOPSIS unload ?switches? fileName unload ?switches? fileName packageName unload ?switches? fileName packageName interp |
︙ | ︙ | |||
253 254 255 256 257 258 259 | This command tries to unload shared libraries previously loaded with load from the application's address space. fileName is the name of the file containing the library file to be unload; it must be the same as the filename provided to load for loading the library. packageName is the name of the package, and is used to compute the name of the unload procedure. interp is the path name of the | | | | 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 | This command tries to unload shared libraries previously loaded with load from the application's address space. fileName is the name of the file containing the library file to be unload; it must be the same as the filename provided to load for loading the library. packageName is the name of the package, and is used to compute the name of the unload procedure. interp is the path name of the interpreter from which to unload the package \(see the interp manual entry for details\); if interp is omitted, it defaults to the interpreter in which the unload command was invoked. If the initial arguments to unload start with - then they are treated as switches. The following switches are currently supported: |
︙ | ︙ | |||
279 280 281 282 283 284 285 | Marks the end of switches. The argument following this one will be treated as a fileName even if it starts with a -. When a file containing a shared library is loaded through the load command, Tcl associates two reference counts to the library file. The first counter shows how many times | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 | Marks the end of switches. The argument following this one will be treated as a fileName even if it starts with a -. When a file containing a shared library is loaded through the load command, Tcl associates two reference counts to the library file. The first counter shows how many times the library has been loaded into normal \(trusted\) interpreters while the second describes how many times the library has been loaded into safe interpreters. As a file containing a shared library can be loaded only once by Tcl \(with the first load call on the file\), these counters track how many interpreters use the library. Each subsequent call to load after the first, simply increaments the proper reference count. unload works in the opposite direction. As a first step, unload will check whether the library is unloadable: an unloadable library exports a special unload procedure. The name of the unload procedure is determined by packageName and whether or not the target interpreter is a safe one. For normal interpreters the name of the initialization procedure will have the form pkg\_Unload, where pkg is the same as packageName except that the first letter is converted to upper case and all other letters are converted to lower case. For example, if packageName is foo or FOo, the initialization procedure's name will be Foo\_Unload. If the target interpreter is a safe interpreter, then the name of the initialization procedure will be pkg\_SafeUnload instead of pkg\_Unload. If unload determines that a library is not unloadable \(or unload functionality has been disabled during compilation\), an error will be returned. If the library is unloadable, then unload will call the unload procedure. If the unload procedure returns TCL\_OK, unload will proceed and decrease the proper reference count \(depending on the target interpreter type\). When both reference counts have reached 0, the library will be detached from the process. The unload procedure must match the following prototype: typedef int Tcl\_PackageUnloadProc\(Tcl\_Interp \*interp, int flags\); The interp argument identifies the interpreter from which the library is to be unloaded. The unload procedure must return TCL\_OK or TCL\_ERROR to indicate whether or not it completed successfully; in the event of an error it should set the interpreter's result to point to an error message. In this case, the result of the unload command will be the result returned by the unload procedure. The flags argument can be either TCL\_UNLOAD\_DETACH\_FROM\_INTERPRETER or TCL\_UNLOAD\_DETACH\_FROM\_PROCESS. In case the library will remain attached to the process after the unload procedure returns \(i.e. because the library is used by other interpreters\), TCL\_UNLOAD\_DETACH\_FROM\_INTERPRETER will be defined. However, if the library is used only by the target interpreter and the library will be detached from the application as soon as the unload procedure returns, the flags argument will be set to TCL\_UNLOAD\_DETACH\_FROM\_PROCESS. The unload command cannot unload libraries that are statically linked with the application. If fileName is an empty string, then packageName must be specified. If packageName is omitted or specified as an empty string, Tcl tries to guess the name of the package. This may be done differently on different platforms. The default guess, which is used on most UNIX platforms, is to take the last element of fileName, strip off the first three characters if they are lib, and use any following alphabetic and underline characters as the module name. For example, the command unload libxyz4.2.so uses the module name xyz and the command unload bin/last.so \{\} uses the module name last. PORTABILITY ISSUES Unix Not all unix operating systems support library unloading. Under such an operating system unload returns an error \(unless -nocomplain has been specified\). Macintosh <Somebody to comment on this?> BUGS If the same file is loaded by different fileNames, it will be loaded into the process's address space multiple times. The behavior of this varies from system to system \(some systems may detect the redundant loads, others may not\). In case a library has been silently detached by the operating system \(and as a result Tcl thinks the library is still loaded\), it may be dangerous to use unload on such a library \(as the library will be completely detached from the application while some interpreters will continue to use it\). SEE ALSO info sharedlibextension, load, safe KEYWORDS binary code, unloading, safe interpreter, shared library |
Name change from tip/101.tip to tip/101.md.
|
| < | < | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 101: Export Tcltest Configuration Author: Don Porter <[email protected]> State: Final Type: Project Vote: Done Created: 11-Jun-2002 Post-History: Tcl-Version: 8.4 ----- # Abstract Proposes public command _tcltest::configure_ to give programmatic control to processing configuration options of the tcltest package. # Rationale During _package require tcltest_, the internal command _ProcessCmdLineArgs_ is evaluated. This command uses the contents of _$::argv_ as option-value pairs to configure several aspects of the tcltest package. This approach leaves two aspect of package configuration hardwired, and outside of the control of users of _tcltest_. First, the timing of configuration is fixed to package load time. Second, the source of configuration data is fixed to be the global variable _argv_. It would improve flexible use of tcltest to export a public command, _tcltest::configure_, that will allow configuration of _tcltest_ by its users at any time and from any source. # Proposal Add and export the command _tcltest::configure_, with the syntax: tcltest::configure ?option? ?value option value ...? With no options, _configure_ returns a list of the available configurable options. With a single _option_ argument, _configure_ returns the corresponding value of that option, or an error if no such option exists. In the most general form, _configure_ accepts an even number of arguments that are alternating options and values, and sets each option to each value. The list of options and acceptable values are to be the same as those currently recognized by _tcltest_ as its command line options. The difference is that this configuration can now be performed programmatically, not only on the command line. With complete programmatic access to _tcltest_ configuration made available, the special customization hooks _processCmdLineArgsHook_ and _processCmdLineArgsAddFlagsHook_ will be deprecated and removed from the documentation. Compatibility support for their existing use will be provided as described below. # Compatibility Many existing test suites have been written depending on the auto-configuration from _$::argv_ at package load time. Some of them may also be using the special customization hooks that allow the addition of more command line options. For compatibility, if the presence of any of these hooks is detected, _tcltest_ will fall back to performing its load-time configuration. Also, if any command that can be influenced by configured values is called prior to any call to _configure_, then automatic configuration from _::argv_ will be performed. # Copyright This document has been placed in the public domain. |
Name change from tip/102.tip to tip/102.md.
|
| < | | | | | | | < | | > | | | | | | | | | | | | | | | > | 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 | # TIP 102: Change [trace list] to [trace info] Author: Reinhard Max <[email protected]> Type: Project Tcl-Version: 8.4 State: Final Created: 12-Jun-2002 Keywords: trace, info, introspection Vote: Done Post-History: ----- # Abstract This TIP proposes to change the name of the introspection subcommand of the _trace_ command from _list_ to _info_. # Rationale Although the functionality of the _trace_ command \(as extended by [[62]](62.md)\) is good, the name of the introspection subcommand, _list_ is not such a good choice: * The name _info_ is already well known for introspection purposes in Tcl \(e.g. [info] and [after info].\) * The name [trace list] could be misunderstood as having to do with tracing lists. * The introspection subcommand to trace could be extended to allow more specific queries along the lines of [info commands], [info procs], and [info vars]. _\(This is outside the scope of this TIP.\)_ Hence, this TIP calls for the _list_ subcommand to be renamed to _info_. \(Note that this also makes the subcommand for introspecting on variable traces more similar to its old form _vinfo_.\) # Copyright This document is placed in the public domain. |
Name change from tip/103.tip to tip/103.md.
|
| < | < | | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | < < < < > > > > | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 103: Argument Expansion Command Author: Peter Spjuth <[email protected]> Author: Donal K. Fellows <[email protected]> Author: Andreas Leitgeb <[email protected]> State: Rejected Type: Project Vote: Done Created: 15-Jun-2002 Post-History: Tcl-Version: 8.5 ----- # Abstract This TIP proposes to add a command that can perform argument expansion in a safe and efficient manner. # Introduction Many commands take a variable number of arguments and often you find yourself with those arguments in a list. This list must then be expanded into individual arguments to the command. This is currently done with eval: eval destroy [winfo children .] This is a bit obscure and also very error prone when the command becomes more complex. It is also inefficient and not object safe, why a command specialised in doing this would be better. # Rationale There have been suggestions of introducing some new syntax to Tcl to handle argument expansion. That is a big and controversial step, and not anything this TIP wants to meddle in. A command can improve every point where eval has shortcomings and thus give a good result with less means. It can also serve as a bridge to a future global syntax. Such a command can be done in several ways and below the choice in this TIP's specification is defended. As examples three statements are used which will be repeated for different alternatives. This is the eval version: eval destroy [winfo children .] eval button .b $stdargs -text \$mytext -bd $border eval exec \$prog $opts1 [getMoreopts] \$file1 \$file2 The eval version would be even more complex if the lists that are to be expanded are not known to be pure. To be really safe the last would be: eval exec \$prog [lrange $opts1 0 end] [lrange [getMoreopts] 0 end] \$file1 \$file2 With the proposed command they become: expand { destroy `[winfo children .] } expand { button .b `$stdargs -text $mytext -bd $border } expand { exec $prog `$opts1 `[getMoreopts] $file1 $file2 } An alternative to having a local syntax is to point at the arguments that should be expanded, either by index: expand {end} destroy [winfo children .] expand {2} button .b $stdargs -text $mytext -bd $border expand {2 3} exec $prog $opts1 [getMoreopts] $file1 $file2 Or by some flag mechanism: expand destroy + [winfo children .] expand button .b + $stdargs -text - $mytext -bd $border expand exec - $prog + $opts1 + [getMoreopts] - $file1 - $file2 Those lack in writability/readability/maintainability in a disturbing manner. For the choice of local syntax one goal is that it should not violate Tcl's rules, which simplifies implementation since Tcl's parser can do the job. Any char that fulfils that could be used but the choice fell on \` for forward compatibility reasons. See below. An alternative syntax could be using enclosing \`\` or some other enclosing construct like: expand { destroy <[winfo children .]> } expand { button .b <$stdargs> -text $mytext -bd $border } expand { exec $prog <$opts1> <[getMoreopts]> $file1 $file2 } Paired characters are good for delimiting things. Here is the beginning; here is the end. But this is not about a new way to delimit things. It is about indicating a boolean choice: expand or do not expand a word into multiple words. Whatever character is chosen to be that indicator, it should be a single, leading one. No pairs. In the specification a restrictive rule was chosen that makes it an error to use \` in a way that do not fit. This is to make it easier to change things in the future should ideas come up for new features. E.g., should this become a global syntax in Tcl 9.0 it can be chosen a bit differently and be backward compatible with the expand command. # Specification A new command "expand" is added. It takes one argument, which contains a Tcl script consisting of one command. The script may contain comments but only one command is permitted. The command is processed in the following manner: 1. Parse into words according to Tcl's standard rules. 2. Any word starting with \` must be followed by a single variable or command substitution. The word is remembered and the \` is removed. 3. Perform Tcl's normal execution steps on the new line up to the point where the command should have been called. 4. Expand the arguments that should be expanded. 5. Execute the command. The return value of expand is the return value of the command. _Note 1:_ A word should really start with \` to trigger expansion which means that words like these are not expanded: cmd "`$temp" \`[something] _Note 2:_ Expansion is only performed with words like: cmd `$var `[somecmd $arg] `$arr([cmd $arg]) Words like these are a syntax error: cmd `word` `$x,$y `[foo]xy[apa] # Forward compatibility One aspect of choosing a syntax here is to think about the future. Should there later be a wish for a global syntax for argument expansion it would be nice if it were the same as the one chosen in the expand command. If an agreement can be made for what may be acceptable in the future, this should affect the specification in this TIP. If a single character like \` is chosen for a global expand syntax it means a backwards compatibility break. So, what chars are likely to be used by people and thus causing problems or confusion when backwards compatibility is broken? Some food for thought about different chars: _ # Word char : # Gets ugly with namespace qualifiers: :$::var ! if !$var {...} * string match *$suffix $line ^ regexp ^$prefix $line ~ cd ~$user | open |$prog . button .$w ; glob -nocomplain .$str = wm geometry .e =$geo @ .x conf -bitmap @$bmp -cursor @$cur < bind . <$left> ; set html <$tag> ( expr ($a + $b) * $c ;# Confuses paren-matching ) # Odd enough as opening, but would confuse any paren-matching + expr $a +$b ;# Same for any operator - % & ? / open /$path ' # Makes more sense as enclosing? ` # Makes more sense as enclosing? > exec foobar >/some/file , append recipients ,[join $header($ccL) ,] {} completely forward-compatible, as {} currently cannot be trailed by anything but whitespace. (This would limit the originally proposed global syntax change to the argument of the expand command) Example usage of those that seem reasonable: expand { exec $prog '$opts1 '[getMoreopts] $file1 $file2 } expand { exec $prog `$opts1 `[getMoreopts] $file1 $file2 } expand { exec $prog ,$opts1 ,[getMoreopts] $file1 $file2 } For comparison, the syntax that has been proposed earlier that would not break backwards compatibility: expand { exec $prog {}$opts1 {}[getMoreopts] $file1 $file2 } expand { exec $prog {expand}$opts1 {expand}[getMoreopts] $file1 $file2 } # Discussion When first issued the TIP caused some discussion on c.l.t. Until a summary is made, here is the thread: <http://groups.google.com/groups?th=9e77d5836b06ab1b> Another thread about it: <http://groups.google.com/groups?th=2ba287be87c2678c> # Reference Implementation Patch \#570201 <http://sourceforge.net/tracker/index.php?func=detail&aid=570201&group\_id=10894&atid=310894> # Copyright This document has been placed in the public domain. |
Name change from tip/104.tip to tip/104.md.
|
| < | < | | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | < | > | > | 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 | # TIP 104: Generalization of the Tk Undo Subsystem Author: Ludwig Callewaert <[email protected]> Author: Larry W. Virden. <[email protected]> State: Final Type: Project Vote: Done Created: 19-Jun-2002 Post-History: Discussions-To: news:comp.lang.tcl Tcl-Version: 8.4 ----- # Abstract This TIP proposes a reimplementation of the Tk Text widget undo feature. The text widget interface is not affected. No functional changes are made at the Tcl level. The purpose of the reimplementation is to move the undo feature from a text only implementation to a general implementation also usable by other widgets. This opens the door to undoing also tag, mark and other operations, and allows for an exposure of the undo stack at the Tcl level. These new features are however not part of this TIP. # Rationale As stated in the abstract, the current implementation of the text widget undo feature only allows for text changes to be undone. The usefulness of the undo feature would increase tremendously if other operations could be undone \(tags, marks, embedded windows, ...\). This was already part of the [[26]](26.md) discussions. This TIP deals with the generalization of the undo stack to cope with these requirements. # Specification As the undo functionality is no longer text widget specific, it has been put in a separate file _generic/tkUndo.c_ along with its header file _generic/tkUndo.h_. The _TkUndoRedoStack_ is a structure containing the undo and redo stacks. These undo and redo stacks are linked lists of _TkUndoAtom_ structures. There are two types of these atoms: the separator \(similar to the previous implementation\) and the command. When the type is command, both an _apply_ and a _revert_ action need to be provided. The apply action is for the redo. The revert action is for the undo. Both are pointers to a _Tcl\_Obj_, so they can \(and should\) contain a Tcl script. The following functions all operating on a _TkUndoRedoStack_ stack are provided to implement the undo/redo functionality. 1. _TkUndoInitStack\(interp\)_: returns a pointer to an initialized TkUndoRedoStack and stores _interp_ in that stack for script evaluation. 2. _TkUndoClearStacks\(stack\)_: clears both the undo and the redo stacks. 3. _TkUndoFreeStack\(stack\)_: clears both undo and redo stacks and frees any memory allocated to _stack_. 4. _TkUndoInsertUndoSeparator\(stack\)_: inserts a separator on the undo stack. Note that there is currently no need for a _TkUndoInsertRedoSeparator_ function, as the redo stack is managed by the internals of _TkUndo_. 5. _TkUndoPushAction\(stack, actionScript, revertScript\)_: pushes an action of the undo stack \(an atom of type command\). _actionScript_ and _revertScript_ are _Tcl\_DString_ pointers that provide the script to redo and undo the action respectively. The redo stack is cleared. 6. _TkUndoRevert\(stack\)_: undo a compound action. Compound means all revert script of action between two separators on the undo stack are evaluated in the stack's interpreter and the actions are moved to the redo stack. Returns TCL\_ERROR when unsuccessful \(stack empty for instance\), and TCL\_OK otherwise. 7. _TkUndoApply\(stack\)_: redo a compound action. The apply script of all actions between two separators on the redo stack is evaluated in the stack's interpreter. The actions are moved to the undo stack. Returns TCL\_ERROR when unsuccessful \(stack empty for instance\), and TCL\_OK otherwise. 8. _TkUndoSetDepth\(stack, maxDepth\)_: sets the maximum number of compound actions stored on the stack to _maxDepth_. By default, stacks are unlimited, and a value of _maxDepth_ <= 0 resets the stack to be unlimited. 9. The option _-maxundo_ is added to the text widget to access the stack limit feature of the text widget's undo stack from the script level. These functions are sufficient to implement the current undo functionality of the text widget, and they have been used for this purpose. # Reference Implementation See patch \#554763 on SourceForge: _ <https://sourceforge.net/tracker/?func=detail&atid=312997&aid=554763&group\_id=12997> _ # Copyright This document has been placed in the public domain. |
Name change from tip/105.tip to tip/105.md.
|
| < | | | | | | < | | | > | | | | | | | | | | | | | | | | | | | < > | | < < | > > | | | < > | | < > | | < < | > > | | | | < > | | < > | | < < | > > | | | > | 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 | # TIP 105: Add Prefix Matching for Switch State: Withdrawn Type: Project Tcl-Version: 8.5 Vote: Pending Post-History: Author: Donal K. Fellows <[email protected]> Created: 03-Jul-2002 Obsoleted-By: 195 ----- # Abstract This TIP adds a new option to the [switch] command to support matching of strings to unique prefixes of patterns, similar to Tcl's existing subcommand-name matching or Tk's option-name matching. # Rationale When code \(particularly in script libraries\) wants to support shortest unique prefix matching in the manner of the Tcl core \(as provided by _Tcl\_GetIndexFromObj_\) currently either the prefixes have to be precomputed \(by hand or by script\) or the matching has to be done backwards. In the first case, this is either error-prone or requires an extra piece of code that has to be developed by the programmer. In the second case, the code has to be converted into a pattern which is matched against the list of supported options in some way, which is either inefficient or has hazards if the string being matched contains characters that are meaningful to the matching engine being used. Instead, it would be far nicer if we could make the core support this directly, so that script authors could just say what they mean. # Proposed Change To support this, I propose modifying the _switch_ command to take an extra option _-prefix_ \(which should be mutually exclusive with _-exact_, _-glob_ and _-regexp_ of course\) to enable prefix matching. When prefix matching is enabled, the arm chosen for execution will be the one such that the switch value is identical to or an unambiguous prefix of its pattern \(i.e. it will not be a prefix of any other pattern listed, unless the pattern of the arm chosen is exactly equal to the switch value.\) If there is no arm whose pattern is an unambiguous prefix of the switch value, the default arm will be selected for execution, or if there is no default arm, the switch command will terminate without an error and with an empty result \(this is in contrast to the behaviour of _Tcl\_GetIndexFromObj_.\) # Examples The command: switch -prefix f { foo { puts "matched foo" } bar { puts "matched bar" } } prints "matched foo". The command: switch -prefix b { bar { puts "matched bar" } boo { puts "matched boo" } default { puts "the default action" } } prints "the default action" \("b" is a prefix of two patterns.\) The command: switch -prefix tcl { tcl { puts "The Tool Command Language" } tk { puts "The Tk Toolkit" } tcl/tk { puts "A cool combination" } } prints "The Tool Command Language" \(although "tcl" is a prefix of two patterns, it matches one of them exactly.\) # Copyright This document has been placed in the public domain. |
Name change from tip/106.tip to tip/106.md.
|
| < | < | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 106: Add Encoding Abilities to the [dde] Command Author: Harald Oehlmann <[email protected]> State: Final Type: Project Vote: Done Created: 13-Aug-2002 Post-History: Tcl-Version: 8.6 ----- # Abstract When using Windows DDE communication with non-Tcl programs, the encoding of the exchanged strings is mostly needed to be the system encoding. Selection of this behaviour should be possible with in the **dde** command should be done by a parameter. # Specification Extend the **dde** commands taking a data argument by the switch **-binary**: > **dde execute** ?**-async**? ?**-binary**? _service topic data_ > **dde poke** ?**-binary**? _service topic item data_ The argument _data_ is taken as a binary string if the **-binary** switch is given. Otherwise, it is interpreted as utf-8. Examples: dde execute -binary CS CS [encoding convertto [encoding system] Äpfel]\0 dde poke -binary CS CS I [encoding convertto [encoding system] Äpfel]\0 # Rationale The communication with DDE with external programs uses the format clipboard _CF\_TEXT_ and the sent text should be coded in the system encoding \(_cp1252_ in my locale\). Most people who use DDE to communicate with, for example, Excel use the fact that what Excel expects \(_cp1252_\) and what Tcl actually sends \(_utf-8_\) is identical for 7-bit values and they don't use 8-bit values. Unfortunately, characters used in languages like German, French, etc., are located over this limit and thus are not transferable. Peter Hardie addressed this point on 2000-10-26 in the Tcl Feature Request at SourceForge \(\#219185: "dde only handles UTF-8 data \(-binary patch available\)" <http://sf.net/tracker/?func=detail&aid=219185&group_id=10894&atid=360894> \). His proposal was to add a **-binary** option. This is a reasonable solution, because any encoding including the system encoding may be used as shown in the upper example. # Reference Implementation See the _tip-106-impl_ branch in Tcl's fossil repository <https://core.tcl.tk/tcl/timeline?r=tip-106-impl> . # Rejected Alternatives I proposed to use a switch ?**-encoding** _encoding_? which would avoid the preparation of an encoded string by **encoding convertto**. DDE is so little used at those days so a minimal support is sufficient. The **dde request** subcommand already has a parameter _-binary_. It is more logical to extend this to the other commands. # Copyright This document has been placed in the public domain |
Name change from tip/107.tip to tip/107.md.
|
| < | < | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 107: Fix the 2-second "raise delay" in Tk Author: Joe English <[email protected]> State: Final Type: Project Created: 28-Aug-2002 Tcl-Version: 8.4 Vote: Done Post-History: ----- # Abstract This TIP explains the genesis of the long delays often associated with the [raise] and [lower] commands under Unix/X with some window managers, as well as describing the solution. # Rationale Currently, Tk's [raise] and [lower] commands do not return to the caller until the operation has completed. Under Unix, the window manager is responsible for changing the stacking order of toplevel windows, so [raise] and [lower] must wait for a notification from the WM before returning. Not all window managers are ICCCM-compliant in this regard, however, so the operation may time out instead. This two-second "raise delay" has been a longstanding, persistent problem in Tk. It has supposedly been fixed several times, but the problem keeps reoccurring under new window managers and new environments. At present, the problem is most noticeable under KDE 2 and KDE 3. # Proposal Change Tk so that [raise] and [lower] return immediately, without waiting for a notification that may not be forthcoming. This should not be be a controversial change. This behaviour is not documented anywhere, and is not observable by Tk programs except via [wm stackorder] \(see [[74]](74.md)\). Moreover, the guarantee is largely meaningless. After [raise] returns, the window _contents_ may still not be visible \(there may be pending <Expose> events, for example\), and the actual position in the stacking order is still subject to window manager intervention. # Compatibility Issues The only Tk programs that would break with this change are ones which expect the return value of [wm stackorder] to reflect the results of any immediately-preceding [raise] and [lower] commands. \(The Tk test suite is one such program, and would need to be modified\). Unfortunately there is no reliable way to fix such programs - [update] will not work, and the ICCCM does not, to the author's knowledge, provide a way to synchronize with the window manager to make sure it has processed all outstanding client requests. Even if it did, this wouldn't help - the raise delay problem only occurs under non-compliant window managers to begin with! Since the stacking order is not observable except through [wm stackorder] - that was the whole point of [[74]](74.md) - no other programs will be affected. \(Note that [wm stackorder] will still work: the only difference is that it may return soon-to-be out-of-date information. Since this is the case already - the user may restack or iconify windows at any time - this change should be low-impact.\) # Reference Implementation See Sourceforge Tk Patch \#601518. <http://sourceforge.net/tracker/index.php?func=detail&aid=601518&group\_id=12997&atid=312997> # Author's Note Could we fast-track this? It's a longstanding problem with a simple fix and ought to make it in before 8.4 goes final. # Detailed Analysis First, some terminology: * _toplevel_: a Tk [toplevel] window. * _wrapper_: an auxiliary window created by Tk to hold the toplevel and its \(optional\) menubar. Initially created as a child of the root window. * _client window_: From the window manager's perspective, any window created as a child of the root window by an X client. Tk wrapper windows are client windows. Most window managers reparent client windows under a new frame window which holds window manager decorations. * _reparent_: Used as a noun, the immediate parent of a wrapper which has been reparented by a window manager. * _frame_: The immediate child of the root window \(or virtual root window\) created by the window manager to hold a client window and its decorations. May or may not be the same as the reparent window. Next, some methodology: The correct way to change the stacking order of a client window is to make a _ConfigureRequest_ on the client window with _stack\_mode_ set appropriately. If the client has not been reparented, then the X server performs the operation directly, and will send a _ConfigureNotify_ back to the client if, and only if, the actual stacking order has changed. \(Raising a window which is already at the top of the stacking order will not result in a _ConfigureNotify_, for example\). If the client window _has_ been reparented \(which is usually the case\), then the window manager intercepts the request and, at its discretion, restacks the frame window instead. It then sends a synthetic _ConfigureNotify_ back to the client, regardless of whether or not it honored the request. If the stacking order is to be changed relative to some other window - that is, if the _sibling_ field is also set - and the client has been reparented, then the _ConfigureRequest_ will fail with a _BadMatch_ error before it gets to the WM. Clients must be prepared to handle this case by catching the error and re-sending a synthetic _ConfigureRequest_ to the root window, which the WM receives and handles as above. See ICCCM section 4.1.5 "Configuring the Window" for the full specification. The Xlib function _XReconfigureWMWindow\(\)_ takes care of all these details. Now, some archaeology: Tk 4.0 did not do this: instead, it called _XConfigureWindow\(\)_ on the _reparent_ window, then waited for a _ConfigureNotify_ on that window. This was wrong on at least two counts. First, the reparent window might not be the same as the frame window, in which case this would have no effect at all. \(In 4DWm and Sawfish, for example, the reparent window is a child of an outer frame window\). Second, it's not ICCCM-compliant \(Tk doesn't own the reparent window and shouldn't be mucking with it\). Tk 4.0 also included several heuristics that attempted to determine when the operation was unnecessary, to avoid waiting for a _ConfigureNotify_ on the reparent that was not forthcoming. In Tk 4.1, the \(incorrect\) call to _XConfigureWindow\(\)_ on the reparent was changed to a \(correct\) call to _XReconfigureWMWindow\(\)_ on the wrapper, but the old heuristic code was left mostly intact. Browsing the CVS logs and the older Tk Changelog, we see that this code has been updated several times to account for new conditions, but ultimately without success: the problem persists. These heuristics are not needed at all under WMs which send a synthetic _ConfigureNotify_ in response to client window stacking order changes. On some non-compliant WMs, however, they may help lessen the problem - more by accident than by design - if the reparent is the same as the frame window then the Tk 4.0 heuristics sometimes still work. But even then the heuristics are not reliable. For instance under KDE 2.2 and KDE 3, calling [raise] twice in succession always results in a 2-second delay. It is the author's opinion that the only way forward is to let [raise] and [lower] run asynchronously, and fix the two-second raise delay once and for all. # Copyright This document is hereby placed in the public domain. |
Name change from tip/108.tip to tip/108.md.
|
| < | < | | | | | | > | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 108: Summary of Changes to Generic Tcl/Tk Code to Enable Mac OS X Port Author: Jim Ingham <[email protected]> State: Final Type: Informative Vote: No voting Created: 29-Aug-2002 Post-History: ----- # Abstract The submission of the changes to generic Tcl/Tk necessary for the Mac OS X port was discussed on the Tcl Core mailing list. In light of the very minor changes to shared code involved, and to facilitate including the port in the 8.4 release, it was decided that we would not hold a formal vote. This informational TIP is offered to summarize the work done, however, and to maintain a more complete record. # What Changes are Required for the Mac OS X Port? These fall into two parts: macosx only changes, and changes that effect generic code. The Mac OS X-only changes again fall into two parts. On the one hand, we introduced new macosx directories to the Tcl and Tk trees, at the same level as the win, unix and mac directories. At present, the _tcl/macosx_ directory only contains one _.c_ file and a project file. The _tk/macosx_ directory is much more substantial. This set of changes manifestly only effects this port, and since something is better than nothing, should be uncontroversial. The other Mac OS X-only part is the addition of Mac OS X specific elements to the _.decls_ files. This should also be uncontroversial, though I had to add some slightly non-trivial code to the _genStubs.tcl_ file to handle the fact that Tk loosely uses "unix" to mean "X11", which for Mac OS X is not the case. The Tcl side of Mac OS X is clearly unix, but the same Tcl can in fact be used with X11 \(there is a native X Server in quite common use on Mac OS X\) and with the Aqua based Tk port. In the end, however, the stubs generated for the generic, mac, win & X11 parts of Tcl/Tk are the same, and there is just some extra logic for the aqua part, so the result effects only Mac OS X code. The generic code changes are quite small - a testament to the design of the Tcl/Tk porting layers. 1. We changed the _configure.in_, _Makefile.in_ and _tcl.m4_ to handle building Tcl in a the Framework form that is common on Mac OS X. 2. I added a bit of code \(conditionalized to Mac OS X\) to _tclUnixInit.c_ \(in the _TclpSetVariables_ function\) to support looking for script files embedded in the Mac OS X Framework bundle. This fits the Mac OS X model better than putting files in _/usr/local_ or such-like. 3. I added a few more elements to the _notifierProcPtr_. For the aqua Tk, we need to swap the Unix notifier with our own, and so we needed more control over the notifier than was allowed. This change has no effect if you don't use it, however. 4. I added a function, _TkGetFirstTextLayout_, which gets the run of text up the the first wrap. I have to get this because the Mac OS X button control doesn't like a newline in the button text. It is a private function, however, so it doesn't cause any incompatibilities. 5. We had to change various places in the Tk script code and the demos where the implicit assumption was made that [string equal $tcl\_platform\(platform\) "unix"] meant you were using X11. To this end, we will add a _windowingsystem_ subcommand to the _tk_ command, and then using it to replace the cases where _tcl\_platform_ was being erroneously checked. This command will return "x11" for an X11 server, "aqua" for the native Mac OS X window manager, "win32" for Windows, and "classic" for Classic MacOS. # Reference Implementation The reference implementation is on the _macosx-8-4-branch_ in the SourceForge CVS repository. # Copyright This document has been placed in the public domain. |
Name change from tip/109.tip to tip/109.md.
|
| < | | | | | | < | | > | | | | | | | | | | > | 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 | # TIP 109: New Look for Checkbutton and Radiobutton on Unix State: Final Type: Project Tcl-Version: 8.5 Vote: Done Post-History: Author: Brian Griffin <[email protected]> Created: 01-Oct-2002 ----- # Abstract This TIP proposes changing the look of the Tk checkbutton and radiobutton widgets on Unix to more closely match the Windows counterparts. # Rationale The current visual aspect of the Unix version checkbutton and radiobutton has proved to be confusing to users. The distinction between selected \(On\) and unselected \(Off\) states are not visually different enough to clearly identify one from another. Indeed, in the rare case where only one checkbutton is present, one cannot tell for certain if the state is On or Off. With a check or dot mark icon \(dependent on the type of widget\) displayed in the Windows version, there is no question about the state of the widget. # Proposed Changes The checkbutton shall \(when the indicator is turned on\) display an check-mark or other distinguishing icon/symbol that clearly indicates an On state. The Off state will be displayed with an empty box. The state values will _not_ be indicated by changing relief or background color. The radiobutton shall \(when the indicator is turned on\) display an dot mark or other distinguishing icon/symbol that clearly indicates a selected or On state. The unselected or Off state shall be displayed with an empty diamond. The state values will _not_ be indicated by changing relief or background color. # Copyright This document has been placed in the public domain. |
Name change from tip/11.tip to tip/11.md.
|
| < | < | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | < > | | | < > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | < > | | | | > | > > > > > > | < < < < < < < | | < > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | < > | | | | | | | | | < > | | | | | | | | < > | | | | | | < > | | | | | | | | | | | | | | | | | | | | | < > | | | | | | | | | | | | | < > | < > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | < > | | | < > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | < > | | | | | < > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | < > | | < > | | | | | | | | | | | < > | | | | < > | | | | | | < > | | | | | < > | | | | | | > < < > | | < > | | | | | | | | | < > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | < > | < > | | | < > | | | | | | | | | | | < > | | > | 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 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 | # TIP 11: Tk Menubutton Enhancement: -compound option for menubutton Author: Todd Helfter <[email protected]> State: Final Type: Project Tcl-Version: 8.4 Vote: Done Created: 16-Nov-2000 Post-History: ----- # Abstract This TIP describes how to change the menubutton in the Tk core to add a -compound option to display both text and images. This behavior already exists in the button widget. # Rationale In order to have a menubutton with both text and images, this change is needed. This change facilitates the use of an image for the menubutton face with text on top. Like the button widget, the -compound option will accept these values: none, center, left, right, top, bottom. # Reference Implementation This TIP proposes to change the internals of the menubutton. The changes necessary to accomplish this are: 1. Extend the structure _TkMenuButton_ in _generic/tkMenubutton.h_ with a new field of type _int_ to hold the value of the compound setting. 2. Add an enumeration of valid -compound options in _generic/tkMenubutton.h_. 3. Modify _generic/tkMenuButton.c_ and _unix/tkUnixMenubu.c_ in such a way to process this new option. Note: The windows port of Tk uses the _unix/tkUnixMenubu.c_ file. So this change is portable to both Unix and windows. 4. Change _tests/menubut.test_ so that the test for configure options checks for 33 instead of the current 32. 5. Change _doc/menubutton.n_ to show the new option under widget specific options. # Copyright This document has been placed in the public domain. # Patch Index: doc/menubutton.n =================================================================== RCS file: /cvsroot/tk/doc/menubutton.n,v retrieving revision 1.3 diff -c -r1.3 menubutton.n *** menubutton.n 2000/08/25 06:58:32 1.3 --- menubutton.n 2000/11/16 14:37:15 *************** *** 26,31 **** --- 26,39 ---- \-disabledforeground \-padx .SE .SH "WIDGET-SPECIFIC OPTIONS" + .OP \-compound compound Compound + Specifies whether the menubutton should display both an image and text, + and if so, where the image should be placed relative to the text. + Valid values for this option are \fBbottom\fR, \fBcenter\fR, + \fBleft\fR, \fBnone\fR, \fBright\fR and \fBtop\fR. The default value + is \fBnone\fR, meaning that the menubutton will display either an image or + text, depending on the values of the \fB\-image\fR and \fB\-bitmap\fR + options. .VS .OP \-direction direction Height Specifies where the menu is going to be popup up. \fBabove\fR tries to Index: generic/tkMenubutton.c =================================================================== RCS file: /cvsroot/tk/generic/tkMenubutton.c,v retrieving revision 1.4 diff -c -r1.4 tkMenubutton.c *** tkMenubutton.c 1999/04/24 01:50:49 1.4 --- tkMenubutton.c 2000/11/16 14:37:16 *************** *** 37,42 **** --- 37,51 ---- }; /* + * The following table defines the legal values for the -compound option. + * It is used with the "enum compound" declaration in tkButton.h + */ + + static char *compoundStrings[] = { + "bottom", "center", "left", "none", "right", "top", (char *) NULL + }; + + /* * Information used for parsing configuration specs: */ *************** *** 113,118 **** --- 122,130 ---- {TK_OPTION_RELIEF, "-relief", "relief", "Relief", DEF_MENUBUTTON_RELIEF, -1, Tk_Offset(TkMenuButton, relief), 0, 0, 0}, + {TK_OPTION_STRING_TABLE, "-compound", "compound", "Compound", + DEF_BUTTON_COMPOUND, -1, Tk_Offset(TkMenuButton, compound), 0, + (ClientData) compoundStrings, 0}, {TK_OPTION_STRING_TABLE, "-state", "state", "State", DEF_MENUBUTTON_STATE, -1, Tk_Offset(TkMenuButton, state), 0, (ClientData) stateStrings, 0}, Index: generic/tkMenubutton.h =================================================================== RCS file: /cvsroot/tk/generic/tkMenubutton.h,v retrieving revision 1.5 diff -c -r1.5 tkMenubutton.h *** tkMenubutton.h 1999/04/16 01:51:19 1.5 --- tkMenubutton.h 2000/11/16 14:37:16 *************** *** 25,30 **** --- 25,39 ---- #endif /* + * Legal values for the "compound" field of TkButton records. + */ + + enum compound { + COMPOUND_BOTTOM, COMPOUND_CENTER, COMPOUND_LEFT, COMPOUND_NONE, + COMPOUND_RIGHT, COMPOUND_TOP + }; + + /* * Legal values for the "orient" field of TkMenubutton records. */ *************** *** 161,166 **** --- 170,179 ---- /* * Miscellaneous information: */ + + int compound; /* Value of -compound option; specifies whether + * the button should show both an image and + * text, and, if so, how. */ enum direction direction; /* Direction for where to pop the menu. * Valid directions are "above", "below", Index: tests/menubut.test =================================================================== RCS file: /cvsroot/tk/tests/menubut.test,v retrieving revision 1.5 diff -c -r1.5 menubut.test *** menubut.test 1999/04/21 21:53:29 1.5 --- menubut.test 2000/11/16 14:37:18 *************** *** 138,144 **** } {3} test menubutton-3.7 {ButtonWidgetCmd procedure, "configure" option} { llength [.mb configure] ! } {32} test menubutton-3.8 {ButtonWidgetCmd procedure, "configure" option} { list [catch {.mb configure -gorp} msg] $msg } {1 {unknown option "-gorp"}} --- 138,144 ---- } {3} test menubutton-3.7 {ButtonWidgetCmd procedure, "configure" option} { llength [.mb configure] ! } {33} test menubutton-3.8 {ButtonWidgetCmd procedure, "configure" option} { list [catch {.mb configure -gorp} msg] $msg } {1 {unknown option "-gorp"}} Index: unix/tkUnixMenubu.c =================================================================== RCS file: /cvsroot/tk/unix/tkUnixMenubu.c,v retrieving revision 1.4 diff -c -r1.4 tkUnixMenubu.c *** tkUnixMenubu.c 1999/09/21 06:43:01 1.4 --- tkUnixMenubu.c 2000/11/16 14:37:18 *************** *** 75,83 **** Pixmap pixmap; int x = 0; /* Initialization needed only to stop * compiler warning. */ ! int y; register Tk_Window tkwin = mbPtr->tkwin; ! int width, height; mbPtr->flags &= ~REDRAW_PENDING; if ((mbPtr->tkwin == NULL) || !Tk_IsMapped(tkwin)) { --- 75,85 ---- Pixmap pixmap; int x = 0; /* Initialization needed only to stop * compiler warning. */ ! int y = 0; register Tk_Window tkwin = mbPtr->tkwin; ! int width, height, fullWidth, fullHeight; ! int imageXOffset, imageYOffset, textXOffset, textYOffset; ! int haveImage = 0, haveText = 0; mbPtr->flags &= ~REDRAW_PENDING; if ((mbPtr->tkwin == NULL) || !Tk_IsMapped(tkwin)) { *************** *** 96,101 **** --- 98,112 ---- border = mbPtr->normalBorder; } + if (mbPtr->image != None) { + Tk_SizeOfImage(mbPtr->image, &width, &height); + haveImage = 1; + } else if (mbPtr->bitmap != None) { + Tk_SizeOfBitmap(mbPtr->display, mbPtr->bitmap, &width, &height); + haveImage = 1; + } + haveText = (mbPtr->textWidth != 0 && mbPtr->textHeight != 0); + /* * In order to avoid screen flashes, this procedure redraws * the menu button in a pixmap, then copies the pixmap to the *************** *** 107,141 **** Tk_Width(tkwin), Tk_Height(tkwin), Tk_Depth(tkwin)); Tk_Fill3DRectangle(tkwin, pixmap, border, 0, 0, Tk_Width(tkwin), Tk_Height(tkwin), 0, TK_RELIEF_FLAT); - - /* - * Display image or bitmap or text for button. - */ ! if (mbPtr->image != None) { ! Tk_SizeOfImage(mbPtr->image, &width, &height); ! ! imageOrBitmap: ! TkComputeAnchor(mbPtr->anchor, tkwin, 0, 0, ! width + mbPtr->indicatorWidth, height, &x, &y); ! if (mbPtr->image != NULL) { ! Tk_RedrawImage(mbPtr->image, 0, 0, width, height, pixmap, ! x, y); ! } else { ! XCopyPlane(mbPtr->display, mbPtr->bitmap, pixmap, ! gc, 0, 0, (unsigned) width, (unsigned) height, x, y, 1); ! } ! } else if (mbPtr->bitmap != None) { ! Tk_SizeOfBitmap(mbPtr->display, mbPtr->bitmap, &width, &height); ! goto imageOrBitmap; } else { ! TkComputeAnchor(mbPtr->anchor, tkwin, mbPtr->padX, mbPtr->padY, ! mbPtr->textWidth + mbPtr->indicatorWidth, ! mbPtr->textHeight, &x, &y); ! Tk_DrawTextLayout(mbPtr->display, pixmap, gc, mbPtr->textLayout, x, y, ! 0, -1); ! Tk_UnderlineTextLayout(mbPtr->display, pixmap, gc, mbPtr->textLayout, ! x, y, mbPtr->underline); } /* --- 118,223 ---- Tk_Width(tkwin), Tk_Height(tkwin), Tk_Depth(tkwin)); Tk_Fill3DRectangle(tkwin, pixmap, border, 0, 0, Tk_Width(tkwin), Tk_Height(tkwin), 0, TK_RELIEF_FLAT); ! imageXOffset = 0; ! imageYOffset = 0; ! textXOffset = 0; ! textYOffset = 0; ! fullWidth = 0; ! fullHeight = 0; ! ! if (mbPtr->compound != COMPOUND_NONE && haveImage && haveText) { ! ! switch ((enum compound) mbPtr->compound) { ! case COMPOUND_TOP: ! case COMPOUND_BOTTOM: { ! /* Image is above or below text */ ! if (mbPtr->compound == COMPOUND_TOP) { ! textYOffset = height + mbPtr->padY; ! } else { ! imageYOffset = mbPtr->textHeight + mbPtr->padY; ! } ! fullHeight = height + mbPtr->textHeight + mbPtr->padY; ! fullWidth = (width > mbPtr->textWidth ? width : ! mbPtr->textWidth); ! textXOffset = (fullWidth - mbPtr->textWidth)/2; ! imageXOffset = (fullWidth - width)/2; ! break; ! } ! case COMPOUND_LEFT: ! case COMPOUND_RIGHT: { ! /* Image is left or right of text */ ! if (mbPtr->compound == COMPOUND_LEFT) { ! textXOffset = width + mbPtr->padX; ! } else { ! imageXOffset = mbPtr->textWidth + mbPtr->padX; ! } ! fullWidth = mbPtr->textWidth + mbPtr->padX + width; ! fullHeight = (height > mbPtr->textHeight ? height : ! mbPtr->textHeight); ! textYOffset = (fullHeight - mbPtr->textHeight)/2; ! imageYOffset = (fullHeight - height)/2; ! break; ! } ! case COMPOUND_CENTER: { ! /* Image and text are superimposed */ ! fullWidth = (width > mbPtr->textWidth ? width : ! mbPtr->textWidth); ! fullHeight = (height > mbPtr->textHeight ? height : ! mbPtr->textHeight); ! textXOffset = (fullWidth - mbPtr->textWidth)/2; ! imageXOffset = (fullWidth - width)/2; ! textYOffset = (fullHeight - mbPtr->textHeight)/2; ! imageYOffset = (fullHeight - height)/2; ! break; ! } ! case COMPOUND_NONE: {break;} ! } ! ! TkComputeAnchor(mbPtr->anchor, tkwin, 0, 0, ! mbPtr->indicatorWidth + fullWidth, fullHeight, ! &x, &y); ! ! if (mbPtr->image != NULL) { ! Tk_RedrawImage(mbPtr->image, 0, 0, width, height, pixmap, ! x + imageXOffset, y + imageYOffset); ! } ! if (mbPtr->bitmap != None) { ! XCopyPlane(mbPtr->display, mbPtr->bitmap, pixmap, ! gc, 0, 0, (unsigned) width, (unsigned) height, ! x + imageXOffset, y + imageYOffset, 1); ! } ! if (haveText) { ! Tk_DrawTextLayout(mbPtr->display, pixmap, gc, mbPtr->textLayout, ! x + textXOffset, y + textYOffset , ! 0, -1); ! Tk_UnderlineTextLayout(mbPtr->display, pixmap, gc, ! mbPtr->textLayout, x + textXOffset, y + textYOffset , ! mbPtr->underline); ! } } else { ! if (mbPtr->image != NULL) { ! TkComputeAnchor(mbPtr->anchor, tkwin, 0, 0, ! width + mbPtr->indicatorWidth, height, &x, &y); ! Tk_RedrawImage(mbPtr->image, 0, 0, width, height, pixmap, ! x + imageXOffset, y + imageYOffset); ! } else if (mbPtr->bitmap != None) { ! TkComputeAnchor(mbPtr->anchor, tkwin, 0, 0, ! width + mbPtr->indicatorWidth, height, &x, &y); ! XCopyPlane(mbPtr->display, mbPtr->bitmap, pixmap, ! gc, 0, 0, (unsigned) width, (unsigned) height, ! x + imageXOffset, y + imageYOffset, 1); ! } else { ! TkComputeAnchor(mbPtr->anchor, tkwin, mbPtr->padX, mbPtr->padY, ! mbPtr->textWidth + mbPtr->indicatorWidth, ! mbPtr->textHeight, &x, &y); ! Tk_DrawTextLayout(mbPtr->display, pixmap, gc, mbPtr->textLayout, ! x + textXOffset, y + textYOffset , ! 0, -1); ! Tk_UnderlineTextLayout(mbPtr->display, pixmap, gc, ! mbPtr->textLayout, x + textXOffset, y + textYOffset , ! mbPtr->underline); ! } } /* *************** *** 252,305 **** TkMenuButton *mbPtr; /* Widget record for menu button. */ { int width, height, mm, pixels; mbPtr->inset = mbPtr->highlightWidth + mbPtr->borderWidth; if (mbPtr->image != None) { Tk_SizeOfImage(mbPtr->image, &width, &height); ! if (mbPtr->width > 0) { ! width = mbPtr->width; ! } ! if (mbPtr->height > 0) { ! height = mbPtr->height; ! } } else if (mbPtr->bitmap != None) { Tk_SizeOfBitmap(mbPtr->display, mbPtr->bitmap, &width, &height); ! if (mbPtr->width > 0) { ! width = mbPtr->width; ! } ! if (mbPtr->height > 0) { ! height = mbPtr->height; ! } ! } else { Tk_FreeTextLayout(mbPtr->textLayout); mbPtr->textLayout = Tk_ComputeTextLayout(mbPtr->tkfont, mbPtr->text, -1, mbPtr->wrapLength, mbPtr->justify, 0, &mbPtr->textWidth, &mbPtr->textHeight); ! width = mbPtr->textWidth; ! height = mbPtr->textHeight; ! if (mbPtr->width > 0) { ! width = mbPtr->width * Tk_TextWidth(mbPtr->tkfont, "0", 1); ! } ! if (mbPtr->height > 0) { ! Tk_FontMetrics fm; ! Tk_GetFontMetrics(mbPtr->tkfont, &fm); ! height = mbPtr->height * fm.linespace; } ! width += 2*mbPtr->padX; ! height += 2*mbPtr->padY; } if (mbPtr->indicatorOn) { ! mm = WidthMMOfScreen(Tk_Screen(mbPtr->tkwin)); ! pixels = WidthOfScreen(Tk_Screen(mbPtr->tkwin)); ! mbPtr->indicatorHeight= (INDICATOR_HEIGHT * pixels)/(10*mm); ! mbPtr->indicatorWidth = (INDICATOR_WIDTH * pixels)/(10*mm) ! + 2*mbPtr->indicatorHeight; ! width += mbPtr->indicatorWidth; } else { ! mbPtr->indicatorHeight = 0; ! mbPtr->indicatorWidth = 0; } Tk_GeometryRequest(mbPtr->tkwin, (int) (width + 2*mbPtr->inset), --- 334,446 ---- TkMenuButton *mbPtr; /* Widget record for menu button. */ { int width, height, mm, pixels; + int avgWidth, txtWidth, txtHeight; + int haveImage = 0, haveText = 0; + Tk_FontMetrics fm; mbPtr->inset = mbPtr->highlightWidth + mbPtr->borderWidth; + + width = 0; + height = 0; + txtWidth = 0; + txtHeight = 0; + avgWidth = 0; + if (mbPtr->image != None) { Tk_SizeOfImage(mbPtr->image, &width, &height); ! haveImage = 1; } else if (mbPtr->bitmap != None) { Tk_SizeOfBitmap(mbPtr->display, mbPtr->bitmap, &width, &height); ! haveImage = 1; ! } ! ! if (haveImage == 0 || mbPtr->compound != COMPOUND_NONE) { Tk_FreeTextLayout(mbPtr->textLayout); + mbPtr->textLayout = Tk_ComputeTextLayout(mbPtr->tkfont, mbPtr->text, -1, mbPtr->wrapLength, mbPtr->justify, 0, &mbPtr->textWidth, &mbPtr->textHeight); ! txtWidth = mbPtr->textWidth; ! txtHeight = mbPtr->textHeight; ! avgWidth = Tk_TextWidth(mbPtr->tkfont, "0", 1); ! Tk_GetFontMetrics(mbPtr->tkfont, &fm); ! haveText = (txtWidth != 0 && txtHeight != 0); ! } ! ! /* ! * If the menubutton is compound (ie, it shows both an image and text), ! * the new geometry is a combination of the image and text geometry. ! * We only honor the compound bit if the menubutton has both text and ! * an image, because otherwise it is not really a compound menubutton. ! */ ! if (mbPtr->compound != COMPOUND_NONE && haveImage && haveText) { ! switch ((enum compound) mbPtr->compound) { ! case COMPOUND_TOP: ! case COMPOUND_BOTTOM: { ! /* Image is above or below text */ ! height += txtHeight + mbPtr->padY; ! width = (width > txtWidth ? width : txtWidth); ! break; ! } ! case COMPOUND_LEFT: ! case COMPOUND_RIGHT: { ! /* Image is left or right of text */ ! width += txtWidth + mbPtr->padX; ! height = (height > txtHeight ? height : txtHeight); ! break; ! } ! case COMPOUND_CENTER: { ! /* Image and text are superimposed */ ! width = (width > txtWidth ? width : txtWidth); ! height = (height > txtHeight ? height : txtHeight); ! break; ! } ! case COMPOUND_NONE: {break;} ! } ! if (mbPtr->width > 0) { ! width = mbPtr->width; ! } ! if (mbPtr->height > 0) { ! height = mbPtr->height; ! } ! width += 2*mbPtr->padX; ! height += 2*mbPtr->padY; ! } else { ! if (haveImage) { ! if (mbPtr->width > 0) { ! width = mbPtr->width; ! } ! if (mbPtr->height > 0) { ! height = mbPtr->height; ! } ! } else { ! width = txtWidth; ! height = txtHeight; ! if (mbPtr->width > 0) { ! width = mbPtr->width * avgWidth; ! } ! if (mbPtr->height > 0) { ! height = mbPtr->height * fm.linespace; ! } } ! } ! ! if (! haveImage) { ! width += 2*mbPtr->padX; ! height += 2*mbPtr->padY; } if (mbPtr->indicatorOn) { ! mm = WidthMMOfScreen(Tk_Screen(mbPtr->tkwin)); ! pixels = WidthOfScreen(Tk_Screen(mbPtr->tkwin)); ! mbPtr->indicatorHeight= (INDICATOR_HEIGHT * pixels)/(10*mm); ! mbPtr->indicatorWidth = (INDICATOR_WIDTH * pixels)/(10*mm) ! + 2*mbPtr->indicatorHeight; ! width += mbPtr->indicatorWidth; } else { ! mbPtr->indicatorHeight = 0; ! mbPtr->indicatorWidth = 0; } Tk_GeometryRequest(mbPtr->tkwin, (int) (width + 2*mbPtr->inset), |
Name change from tip/110.tip to tip/110.md.
|
| < | < | | | | | | | > | | | | | | | | | | | | | | > | 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 | # TIP 110: Add a Tristate Mode to the Checkbutton and Radiobutton Author: Brian Griffin <[email protected]> State: Final Type: Project Vote: Done Created: 01-Oct-2002 Post-History: Tcl-Version: 8.5 ----- # Abstract This TIP proposes adding a third value \(tristate\) to the checkbutton and radiobutton widgets and corresponding display. # Rationale In order to meet more demanding requirements of todays complex graphical user interfaces, it would help add to the functionality of the basic checkbutton and radiobutton widgets. To support using checkbuttons and radiobuttons along with multiple selection, it is necessary for these buttons to be able to display a third state, i.e., both On and Off. This indicates the situation where a property has a particular value for some members of a selection set, but not others. # Proposed Change The change would add a third "tristate" value to current On Off values of the checkbutton and radiobutton widgets. The widget would then display the check/dot mark \(as appropriate\) along with a "grayed" background, for example. When the checkbutton or radiobutton is invoked \(i.e. clicked on\) it would behave exactly as it does currently, setting the variable to the On value. There is a concern that the Unix version of these widgets do not have a sufficiently different appearance when in the tristate state compared with the On and Off states. This issue is addressed in [[109]](109.md). # Propsal Specifics 1. Identify a third, platform specific, presentation \(e.g. check with grayed background\) to represent the tristate value, 1. Add the option "-tristatevalue" to specify the match value only. The default value of this option will be "\{\}", 1. Change the behavior to display the indeterminate or tristate presentation when the associated variable's value matches the -tristatevalue, and 1. Add the option "-tristateimage" to specify an image to display \(in place of the image option\) when the checkbutton or radiobutton has the tristate value \(as defined above.\) # Copyright This document has been placed in the public domain. |
Name change from tip/111.tip to tip/111.md.
|
| < | < | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | < > | | | < | | > | | | < > | | | | | | | | | | > | 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 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 | # TIP 111: Dictionary Values and Manipulators Author: Donal K. Fellows <[email protected]> Author: David S. Cargo <[email protected]> State: Final Type: Project Vote: Done Created: 05-Oct-2002 Post-History: Tcl-Version: 8.5 ----- # Abstract This TIP proposes adding a standard value format \(and supporting commands\) to Tcl that implements a value-to-value mapping, just as Tcl's list values can be regarded as implementing a number-to-value mapping. # Rationale What is a dictionary? It is a translation from arbitrary values to arbitrary values, often also known as an associative map. Many computer languages, especially higher-level ones, have them as part of the language or the standard library. It would be nice to have them in Tcl too. Now, I realise that Tcl already contains arrays which provide dictionary functionality, but they are not quite the same thing. Tcl's arrays are collections of variables indexable by name, and not collections of values. This has some far-reaching implications; it is possible to set traces on individual elements of the array, but it is not possible to pass the array by value. However, one of the main concerns is the sheer cost of arrays in terms of memory space; aside from the hash table used as the core of the implementation \(and the representations of the keys and values, of course\) there is a substantial overhead for each array to support traces on the array as a whole, plus a similar overhead _per element_ that stems from the fact that elements are variables in their own right. By contrast, a dictionary value should be a lot more frugal. # Value Syntax and Semantics Naturally, it is desirable for dictionary values to have human-readable forms that are similar to those that currently exist. I propose using _key value key value ..._ form with list-style quoting for keys and values that contain characters that are significant to Tcl, which should be immediately familiar to users of the **array get** and **array set** commands. No special interpretation will be placed on the amount of whitespace separating keys and values, just as with lists \(indeed, any list with an even number of elements can be regarded as a dictionary.\) For example, the following value represents a mapping from selected languages to a possible program to invoke to compile them: C gcc C++ g++ FORTRAN f77 Java javac Empty dictionaries are those that contain no mappings from keys to values. Any representation of an empty list will also be a representation of an empty dictionary. There is no upper bound on the number of items that a dictionary may hold. It should be specially noted that dictionary values have copy-on-write semantics just like lists. This means that if I hand a dictionary value into a procedure as an argument, and that procedure updates the variable containing that value, the value as seen by the caller will not have changed. This is in complete contrast with arrays which cannot \(currently\) be passed by value other than through using **array get** to convert the array to a list form and **array set** to convert back again. This specification does not state what order the keys and values are listed in. That depends on the implementation. # Command Syntax and Semantics I propose that all operations that work with dictionary values \(where not done through adaptations of existing commands\) will go through the **dict** command. The alternatives are "array" which is already in use, "dictionary" which is rather long for what I believe will be a fairly commonly used command, "alist" \(association list\) which is probably too easy to confuse with existing commands, and "map" which is probably better reserved for future use as something for applying an operation to a list \(or other collection of values\), "hash" \(which is perhaps too common\), and "table" \(which is used for this type of data structure in the Icon programming language\). Most subcommands operate on either a dictionary value \(_exists_, _for_, _get_, _info_, _keys_, _remove_, _replace_, _size_, and _values_\), or on a variable containing a dictionary value \(_append_, _incr_, _lappend_, _set_, and _unset_\). Proposed subcommands: dict create: Make a dictionary. > **dict create** ?_key1 value1 key2 value2 ..._? > This will create a new dictionary from the given keys and values and return it as the result. The command will take an even number of arbitrary strings \(or other objects, naturally\) and will use the first, third, fifth, etc. as keys and the second, fourth, sixth, etc. as values. From the point of view of string representations, this command will behave the same as the **list** command with an even number of arguments. There is no restriction on the possible representations of keys or values. It is legal to call this command with no arguments at all, which creates an empty dictionary. dict get: Get value for given key. > **dict get** _dictionaryValue_ ?_key ..._? > Given a dictionary value \(first argument\) and a key \(second argument\), this will retrieve the value for that key. Where several keys are supplied, the behaviour of the command shall be as if the result of **dict get** _dictVal key_ was passed as the first argument to **dict get_ with the remaining arguments as second \(and possibly subsequent\) arguments. This facilitates lookups in nested dictionaries. For example, the following two commands are equivalent: dict get $dict foo bar spong dict get [dict get [dict get $dict foo] bar] spong > If no keys are provided, dict would return a list containing pairs of elements in a manner similar to **array get**. That is, the first element of each pair would be the key and the second element would be the value for that key. > It is an error to attempt to retrieve a value for a key that is not present in the dictionary. dict replace: Create a new dictionary that is a copy of an old one except with some values different or some extra key/value pairs added. > **dict replace** _dictionaryValue_ ?_key value ..._? > This is very much the analogue of **lreplace**, taking a dictionary value as its first argument and then a list of key/value pairs. The result of the command is a new dictionary value that is a copy of the supplied dictionary other than that whenever a key is one of those supplied to this command, the returned dictionary will map that key to the associated value. It is legal for this command to be called with no key/value pairs, but illegal for this command to be called with a key but no value. dict remove: Create a new dictionary that is a copy of an old one except without the key/value mappings whose keys are listed. > **dict remove** _dictionaryValue_ ?_key key ..._? > This operation does what **dict replace** can't do; removes keys and values. The result of the command is a new dictionary value that does not contain mappings for any of the keys listed; it is not an error if either there are no keys listed, or if any of the listed keys does not exist in the supplied dictionary. dict set: Set value for given key in a dictionary in a variable. > **dict set** _dictionaryVar key_ ?_key ..._? _value_ > This operation takes the name of a variable containing a dictionary value and places an updated dictionary value in that variable containing a mapping from the given key to the given value. In a manner analogous to **lset**, where multiple keys are present, they do indexing into nested dictionaries. dict unset: Remove association for given key in a dictionary in a variable. > **dict unset** _dictionaryVar key_ ?_key ..._? > This operation takes the name of a variable containing a dictionary value and places an updated dictionary value in that variable that does not contain a mapping for the given key. Where multiple keys are present, this describes a path through nested dictionaries to the mapping to remove. At least one key must be specified. dict keys: List all keys \(with optional criteria matching\) in dictionary. > **dict keys** _dictionaryValue_ ?_globPattern_? > Return a list of all keys in the given dictionary value. If a pattern is supplied, only those keys that match it \(according to the rules of **string match**\) will be returned. The returned keys will be in an arbitrary implementation-specific order. dict values: List all values \(with optional criteria matching\) in the dictionary. > **dict values** _dictionaryValue_ ?_globPattern_? > Return a list of all values in the given dictionary value. If a pattern is supplied, only those values that match it \(according to the rules of **string match**\) will be returned. The returned keys will be in an arbitrary implementation-specific order, though where no pattern is supplied the _i_th key returned by **dict keys** will be the key for the _i_th value returned by **dict values** applied to the same dictionary value. dict for: Iterate across all key/value mappings in the dictionary. > **dict for** \{_keyVar valueVar_\} _dictionaryValue body_ > This takes three arguments, the first a pair of variable names \(for the key and value respectively of each mapping in the dictionary\), the second the dictionary value to iterate across, and the third a script to be evaluated for each mapping with the key and value variables set appropriately \(in the manner of **foreach**.\) The result of the command is an empty string. If any evaluation of the body generates a _TCL\_BREAK_ result, no further pairs from the dictionary will be iterated over and the **dict for** command will terminate successfully immediately. If any evaluation of the body generates a _TCL\_CONTINUE_ result, this shall be treated exactly like a normal _TCL\_OK_ result. dict filter: Create a new dictionary from an old one containing just a selection of key/value pairs. > **dict filter** _dictionaryValue_ **key** _globPattern_ > **dict filter** _dictionaryValue_ **value** _globPattern_ > **dict filter** _dictionaryValue_ **script** \{_keyVar valueVar_\} _script_ > This takes a dictionary value and returns a new dictionary that contains just those key/value pairs that match the specified rule. Three rules are outlined above. The **key** rule only matches those key/value pairs whose keys match the given glob-style pattern. The **value** rule only matches those key/value pairs whose values match the given glob-style pattern. The **script** rule tests for matching by assigning the key to the _keyVar_ and the value to the _valueVar_, and then evaluating the given script which should return a boolean value \(with the key/value pair only being included in the result of the **dict filter** when a true value is returned.\) dict append: Append a string to the value for a particular key in the dictionary. > **dict append** _dictionaryVar key_ ?_string ..._? > This appends the given string \(or strings\) to the value that the given key maps to in the dictionary value contained in the given variable, writing the resulting dictionary value back to that variable. Non-existent keys are treated as if they map to an empty string. dict incr: Increment the value for a particular key in the dictionary. > **dict incr** _dictionaryVar key_ ?_increment_? > This adds the given increment value \(an integer that defaults to 1 if not specified\) to the value that the given key maps to in the dictionary value contained in the given variable, writing the resulting dictionary value back to that variable. Non-existent keys are treated as if they map to 0. It is an error to increment a value for an existing key if that value is not an integer. dict lappend: Append an item to the list-value for a particular key in the dictionary. > **dict lappend** _dictionaryVar key_ ?_item ..._? > This appends the given items to the list value that the given key maps to in the dictionary value contained in the given variable, writing the resulting dictionary value back to that variable. Non-existent keys are treated as if they map to an empty list, and it is legal for there to be no items to append to the list. It is an error for the value that the key maps to to not be representable as a list. dict exists: Test whether a mapping exists for a key. > **dict exists** _dictionaryValue key_ ?_key ..._? > This returns a boolean value indicating whether the given key \(or path of keys through a set of nested dictionaries\) exists in the given dictionary value. This returns a true value exactly when **dict get** on that path will succeed. dict size: Get the number of key/value mappings in a dictionary. > **dict size** _dictionaryValue_ > This returns the size of the dictionary, which will be exactly half the value that **llength** _dictionaryValue_ would return. It is an error to apply this command to a non-dictionary value. dict info: Get implementation-specific information about the dictionary value. > **dict info** _dictionaryValue_ > This returns information \(intended for display to people\) about the given dictionary though the format of this data is dependent on the implementation of the dictionary. For dictionaries that are implemented by hash tables, it is expected that this will return the string produced by _Tcl\_HashStats\(\)_. # Other Related Changes There are a few other commands that change: * **array set** will take a dictionary instead of \(or as well as\) a list as its final argument. * **array get** will return a dictionary. * **string map** will take a dictionary instead of \(or as well as\) a list as its map argument. Naturally, dictionary handling will form its own maintenance area. [[16]](16.md) and [[24]](24.md) will be updated as necessary. # C API There will be a new public structure and a few new public functions to allow C-level access to dictionary values: The new structure \(called _Tcl\_DictSearch_\) will be there to allow for searches \(i.e. traversals\) of a dictionary. This TIP does not specify the fields of the structure; the declaration is just to allow for allocation of these structures on the C stack. Many public API functions are capable of generating error messages; these generally indicate some type-conversion failure. Sharing constraint violations \(where applicable\) cause panics as they indicate basic programming errors which should not be causable by scripts. The public API functions are: > Tcl\_Obj \***Tcl\_NewDictObj**\(void\); > Tcl\_Obj \***Tcl\_DbNewDictObj**\(CONST char \*_file_, int _line_\); These functions \(in non-debug and debug versions\) create a new dictionary object and return it. > int **Tcl\_DictObjPut**\(Tcl\_Interp \*_interp_, Tcl\_Obj \*_dictPtr_, Tcl\_Obj \*_keyPtr_, Tcl\_Obj \*_valuePtr_\); This function inserts a new key/value pair into a dictionary, or updates a key/value pair already in the dictionary. The dictionary object must be unshared. Note that both the key and value objects will have their reference count increased. The return value is a normal TCL\_OK/TCL\_ERROR result, with the _interp_ for error reporting. > int **Tcl\_DictObjGet**\(Tcl\_Interp \*_interp_, Tcl\_Obj \*_dictPtr_, Tcl\_Obj \*_keyPtr_, Tcl\_Obj \*\*_valuePtrPtr_\); This function looks up the value for a key in a dictionary. The variable pointed to by the _valuePtrPtr_ argument is updated to contain a reference to the value, or a NULL if there is no mapping for the key in the dictionary. No reference counts are manipulated by this function. The return value is a normal TCL\_OK/TCL\_ERROR result, with the _interp_ for error reporting. > int **Tcl\_DictObjRemove**\(Tcl\_Interp \*_interp_, Tcl\_Obj \*_dictPtr_, Tcl\_Obj \*_keyPtr_\); This function removes the key/value pair with the given key from the dictionary. It is not an error if the key is not present in the dictionary. The dictionary must be unshared. The return value is a normal TCL\_OK/TCL\_ERROR result, with the _interp_ for error reporting. > int **Tcl\_DictObjSize**\(Tcl\_Interp \*_interp_, Tcl\_Obj \*_dictPtr_, int \*_sizePtr_\); This function updates the integer variable pointed to by _sizePtr_ with the number of key/value pairs in the dictionary. The return value is a normal TCL\_OK/TCL\_ERROR result, with the _interp_ for error reporting. > int **Tcl\_DictObjFirst**\(Tcl\_Interp \*_interp_, Tcl\_Obj \*_dictPtr_, Tcl\_DictSearch \*_searchPtr_, Tcl\_Obj \*\*_keyPtrPtr_, Tcl\_Obj \*\*_valuePtrPtr_, int \*_donePtr_\); This function starts a search of \(i.e. iteration over\) the given dictionary, using the structure pointed to by _searchPtr_ as context. The return value is a normal TCL\_OK/TCL\_ERROR result, with the _interp_ for error reporting. Three variables are updated to indicate what was found; _keyPtrPtr_ is used for reporting the key of a key/value pair and _valuePtrPtr_ is used for reporting the corresponding value. Finally, _donePtr_ is used for indicating whether the search has found all the values; if the variable it points to is set to 1 there are no key/value pairs in the dictionary \(i.e. the variables pointed to by _keyPtrPtr_ and _valuePtrPtr_ were not updated\), but if the variable is set to 0, a key/value pair was found and _Tcl\_DictObjNext\(\)_ should be called to discover whether that was the last value or if there are further ones in the dictionary. Note that if this function indicates that the search is not done but the calling code wishes to extract no further values from the dictionary, _Tcl\_DictObjDone\(\)_ _must_ be called to release the internal locks on the representation of the value. > void **Tcl\_DictObjNext**\(Tcl\_DictSearch \*_searchPtr_, Tcl\_Obj \*\*_keyPtrPtr_, Tcl\_Obj \*\*_valuePtrPtr_, int \*_donePtr_\); This function gets the next key/value pair from the search of a dictionary, using the search referenced by _searchPtr_. The meaning of the _keyPtrPtr_, _valuePtrPtr_ and _donePtr_ variables is much the same as in _Tcl\_DictObjFirst\(\)_, along with the restriction that if the function indicates that the search is not done but the calling code wishes to extract no further values from the dictionary, _Tcl\_DictObjDone\(\)_ _must_ be called to release the internal locks on the representation of the value. > void **Tcl\_DictObjDone**\(Tcl\_DictSearch \*_searchPtr_\); This function terminates a search of a dictionary before all the values in the dictionary have been iterated over, releasing the internal locks on the dictionary representation. > int **Tcl\_DictObjPutKeyList**\(Tcl\_Interp \*_interp_, Tcl\_Obj \*_dictPtr_, int _keyc_, Tcl\_Obj \*CONST \*_keyv_, Tcl\_Obj \*_valuePtr_\); This function is a variant on _Tcl\_DictObjPut\(\)_ that takes a list of keys so as to work with nested dictionaries. > int **Tcl\_DictObjRemoveKeyList**\(Tcl\_Interp \*_interp_, Tcl\_Obj \*_dictPtr_, int _keyc_, Tcl\_Obj \*CONST \*_keyv_\); This function is a variant on _Tcl\_DictObjRemove\(\)_ that takes a list of keys so as to work with nested dictionaries. # Examples Counting the number of unique words in a file and the number of times each word occurs: set f [open someFile.txt] set contents [read $f] close $f foreach word [regexp -all -inline {\w+} $contents] { dict incr count $word } puts "There are [dict size $count] unique words." foreach word [lsort -dictionary [dict keys $count]] { puts "${word}: [dict get $count $word] occurrences" } A localisable **string toupper** implementation: set capital [dict create C [dict create]] foreach c {abcdefghijklmnopqrstuvwxyz} { dict set capital C $c [string toupper $c] } dict set capital en [dict get $capital C] # ... and so on for other supported languages ... set upperCase [string map [dict get $capital $env(LANG)] $string # Copyright This document has been placed in the public domain. ---- # Appendices _These appendices are not formally part of the proposal and exist merely to help understanding._ # ~ Implementation Notes Implement using hash tables \(of course.\) Need efficient ways to convert to/from lists, perhaps making lists know what's going on underneath the covers? # ~ Future Directions Alternate implementations of mappings, like trees or disk-backed databases? |
Name change from tip/112.tip to tip/112.md.
|
| < | < | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | < > | | | | | | | < < < > > > | | | | | | | | | | | | | | | | | | | | < > | | | | | | | | < > | | < > | | | | | < > | | | | | | | | | | | < > | | | | | | | | | | < > | | | | | | | < > | < | > | | | | | | | | > | 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 276 277 278 279 280 281 282 283 284 285 | # TIP 112: Ensembles are Namespaces are Commands Author: Donal K. Fellows <[email protected]> State: Final Type: Project Vote: Done Created: 10-Oct-2002 Post-History: Tcl-Version: 8.5 ----- # Abstract This TIP proposes unifying the concept of ensembles \(from [Incr Tcl]\) with namespaces and commands. It also adds control of command rewriting to allow for more efficient support for object systems like Snit. # Rationale Tcl's subcommand-style command collections \(e.g. _array_, _info_, _string_, _interp_, etc.\) are a very intuitive and popular way of structuring collections of related commands. However, it is quite awkward to write Tcl code that behaves that way. Users of [Incr Tcl] have access to ensembles which provide that, but it would be a very useful feature for many other uses too. At the same time, it is becoming clear that many applications want to commonly refer to commands inside other namespaces directly \(instead of through the [namespace import] mechanism\) but the syntax for doing this is verbose and not as elegant as it might be. I believe that the same solution can address these two problems in one go, and make the language stronger and more usable for it. Furthermore, by giving the programmer control over the mapping from the ensemble subcommands to their implementing commands, we can build a simple class system on the cheap since we can, in effect, import commands from elsewhere into the ensemble. By extending the mapping so that it allows the specification of not just the implementing command, but also some leading arguments to that command \(similar to what you can do with the [interp alias] mechanism\) this becomes a very powerful mechanism indeed. Finally, a sophisticated extra capability is the addition of an unknown subcommand callback to allow the creator of the ensemble to specify a customized strategy for handling subcommands that are not recognized by the ensemble machinery. This allows an ensemble to be dynamically updated to include those subcommands that the user asks for, which is a potential route for doing things like using an ensemble as a wrapper round a Tk widget. # Proposed Change I propose to add a new subcommand to the [namespace] command, _ensemble_, that creates and manipulates the ensemble command for a namespace. Each namespace may have any number of ensemble commands associated with it, with the default name of an ensemble command being the fully-qualified name of the namespace itself, though it will be legal to rename ensemble commands \(anyone wanting to track such events should use the [trace] command.\) Tcl will not create an ensemble command for any namespace by default. The [namespace ensemble] command will have the following subcommands: create: For creating a new ensemble for the _current_ namespace. The command takes a list of option value pairs \(as defined below\) to set the ensemble up with. As stated above, the default command name is exactly the name of the namespace, but any other name may be supplied \(via the -command option\); if it does not start with a namespace separator, the name will be taken as being relative to the current namespace. If another command with the same name exists, it is deleted as part of the creation of the ensemble. configure: For reading and writing the configuration of a particular ensemble. The command takes an argument specifying the name of the ensemble to configure, and then works with either no extra arguments \(when it retrieves the entire ensemble configuration\), one extra argument \(the name of the option to retrieve\), or a list of option value pairs to configure the ensemble with. This command returns an error if applied to anything that is not an ensemble. exists: This subcommand \(which takes a single argument\) tests whether a command \(with the given name\) exists and is an ensemble. This command only returns an error if the wrong number of arguments are supplied. The options available for creation and configuring are: -subcommands: This option \(if non-empty\) specifies a list of ensemble subcommands that the ensemble supports. It does not need to be sorted. Each command is mapped according to the dictionary in the _-map_ option \(if a non-empty map is present and the command has a mapping\) or to the correspondingly named command \(which is not required to exist at the time this is specified\) in the context namespace. -map: This option \(if non-empty\) specifies a dictionary that maps from ensemble subcommand names to lists of arguments to substitute into the ensemble invokation in place of the ensemble command name and the subcommand name. See the _-subcommands_ option for the meaning of this option when that option is also non-empty. If this option is empty and the _-subcommands_ option is empty too, the namespace will use the exported commands of the namespace as its command set, dynamically determining them \(subject to cacheing\) every time the ensemble is _invoked_. Note that the words in the dictionary values that give the commands to map to \(as opposed to any arguments to them\) are always resolved \(if not absolute\) relative to the namespace which is running [namespace ensemble create] or [namespace ensemble configure]. -prefixes: This boolean option \(which is on by default\) controls whether unambiguous prefixes of ensemble commands are recognized as if they were the fully specified ensemble command names. -unknown: This provides \(when non-empty\) a partial command to handle the case where an ensemble subcommand is not recognized and would otherwise generate an error. When empty \(the default\) an error \(in the style of _Tcl\_GetIndexFromObj_\) is generated whenever the ensemble is unable to determine how to implement a particular subcommand. > See _Unknown Handler Behaviour_ below for details of how the ensemble interacts with its unknown handler. Ensemble creation takes an extra option value pair: -command: This option allows you to override what the name of the ensemble to create is. Ensemble configuring allows the querying of an extra read-only option: -namespace: This _read-only_ option allows the retrieval of the name of the namespace that the ensemble was created in. Given an ensemble command created by the above mechanism, calling the command will first of all match the subcommand to its implementing command \(or command/argument list, as derived from the dictionary\) in a manner that will be recognizably similar to that enforced by _Tcl\_GetIndexFromObj\(\)_ \(unless the _-unknown_ option override this behaviour.\) For details of how the ensemble determines what its subcommands are, please see the _-subcommands_ and _-map_ options above. Then the ensemble command will rewrite the command and arguments so that the ensemble command and subcommand are replaced by the implementing command and any specified arguments, with the resulting word list being fed to _Tcl\_EvalObjv\(\)_ for execution. Note that this does not increase the stack depth in terms of [uplevel], and that the implementing command may itself be an ensemble command. Note that if the namespace for an ensemble is deleted, the ensemble will also be deleted though there is no lifetime constraint in the other direction \(i.e. using [rename $theEnsemble {}] will not cause the namespace to vanish.\) Obviously, any ensemble which has the global namespace backing it up will have the same natural lifespan as the hosting Tcl interpreter. # Unknown Handler Behaviour If an unknown handler is specified for an ensemble, that handler is called when the ensemble command would otherwise return an error due to it being unable to decide which subcommand to invoke. The exact conditions under which that occurs are controlled by the _-subcommands_, _-map_ and _-prefixes_ options as described above. To execute the unknown handler, the ensemble mechanism takes the specified -unknown option and appends each argument of the attempted ensemble command invocation \(including the ensemble command itself, expressed as a fully qualified name\). It invokes the resulting command in the scope of the attempted call. If the execution of the unknown handler terminates normally, the ensemble engine reparses the subcommand \(as described below\) and tries to dispatch it again, which is ideal for when the ensemble's configuration has been updated by the unknown subcommand handler. Any other kind of termination of the unknown handler is treated as an error. The result of the unknown handler is expected to be a list \(it is an error if it is not\). If the list is an empty list, the ensemble command attempts to look up the original subcommand again and, if it is not found this time, an error will be generated just as if the -unknown handler was not there \(i.e. for any particular invokation of an ensemble, its unknown handler will be called at most once.\) This makes it easy for the unknown handler to update the ensemble or its backing namespace so as to provide an implementation of the desired subcommand and reparse. When the result is a non-empty list, the words of that list are used to replace the ensemble command and subcommand, just as if they had been looked up in the -map. It is up to the unknown handler to supply all namespace qualifiers if the implementing subcommand is not in the namespace of the caller of the ensemble command. Also note that when ensemble commands are chained \(e.g. if you make one of the commands that implement an ensemble subcommand into an ensemble, in a manner similar to the text widget's _tag_ and _mark_ subcommands\) then the rewrite happens in the context of the caller of the outermost ensemble. That is to say that ensembles do not in themselves place any namespace contexts on the Tcl call stack. Where an empty -unknown handler is given \(the default\), the ensemble command will generate an error message based on the list of commands that the ensemble has defined \(formatted similarly to the error message from _Tcl\_GetIndexFromObj\(\)_\). This is the error that will be thrown when the subcommand is still not recognized during reparsing. It is also an error for an -unknown handler to delete its namespace. # Examples namespace eval carrot { namespace export foo bar potato namespace ensemble create ;# Creates command ::carrot proc foo {} {puts 1} ;# Exported proc bar {} {puts 2} ;# Exported proc boo {} {puts 3} ;# Not exported namespace eval turnip { ;# Not exported namespace export alpha proc alpha {} {puts 4} ;# Exported proc beta {} {puts 5} ;# Not exported namespace ensemble create } namespace eval potato { ;# Exported proc north {x} {puts 6,$x} ;# Not exported proc south {x} {puts 7,$x} ;# Not exported # Notice we resolve names locally, and Tcl metachars are not special namespace ensemble create -map { north {north [$meta[$chars} } } } carrot foo ;# Prints 1 carrot bar ;# Prints 2 carrot b ;# Also prints 2 ("boo" not exported) carrot ? ;# ERROR: Alternatives "bar", "foo" and "potato" carrot potato ;# ERROR: Missing argument carrot potato ? ;# ERROR: Try "north" instead carrot potato north ;# Prints 6,[$meta[$chars carrot turnip alpha ;# ERROR: "turnip" not known carrot::turnip alpha ;# Prints 4 carrot::turnip::beta ;# Prints 5 rename ::carrot::potato ::spud spud north ;# Prints 6,[$meta[$chars spud south ;# ERROR: "south" not known carrot potato north ;# ERROR: No ::carrot::potato command # Reconfigure spud; notice we get different name resolution now! namespace ensemble configure spud -map { north {puts NORTH} south {puts SOUTH} } spud north ;# Prints NORTH spud south ;# Prints SOUTH namespace delete carrot spud north ;# ERROR: spud command already deleted namespace eval A { proc a args {puts A::a=>$args} } namespace eval B { proc b args {puts B::b=>$args} } # Create an ensemble in the global namespace namespace ensemble create -command C -map { eg1 {::A::a foo bar} eg2 {::B::b 1 2 3} eg3 ::string } C eg1 spong ;# Prints A::a=>foo bar spong C eg2 evil code {[exit]} ;# Prints B::b=>1 2 3 evil code [exit] C eg3 length qwertyuiop ;# Returns 10 # An example demonstrating the use of -unknown to do delegation # This uses an ensemble to add a subcommand to a frame package require Tk rename [frame .f] _impl.f namespace ensemble create -command .f -unknown {delegate _impl.f} -map { flash {flashFrame _impl.f} } # General delegation framework handler proc delegate {target ensemble subcmd args} { # Read the current map set map [namespace ensemble configure $ensemble -map] # Update it to include the new subcommand dict set map $subcmd [list $target $subcmd] # Install back into the ensemble namespace ensemble configure $ensemble -map $map # Result is empty string, so we reparse return {} } # Our new subcommand implementation proc flashFrame w { set bg [$w cget -background] foreach colour {black white black white black white} { $w configure -background $colour update idletasks after 150 } $w configure -background $bg } # Consequences Many commands in both Tcl and Tk would benefit from leveraging this, and it would enable straight-forward implementations of things like [[65]](65.md) in pure Tcl code. It would also make doing things like partial exposure of ensemble-like commands in safe interpreters much easier. # Sample Implementation <http://sf.net/tracker/?func=detail&aid=786509&group\_id=10894&atid=310894> # Copyright This document has been placed in the public domain. # Acknowledgements Thanks very much to Joe English, Don Porter and Kevin Kenny for their suggestions in the development of this TIP. Without them, it would have been a far worse suggestion. And thanks to Will Duquette for writing a piece of software \(Snit\) that would benefit immensely from pushing the ensemble stuff as hard as possible and then a bit. :^\) |
Name change from tip/113.tip to tip/113.md.
|
| < | < | | | | | | | > | | | | | | | | | | | | | | | | | | > | 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 | # TIP 113: Multi-Line Searches in the Text Widget Author: Vince Darley <[email protected]> State: Final Type: Project Vote: Done Created: 11-Oct-2002 Post-History: Tcl-Version: 8.5 ----- # Abstract This TIP proposes enhancing the implementation of the _$textwidget search_ subcommand to allow matching of both exact strings and regexp patterns which span multiple lines, and to allow reporting on all matches. # Proposal If the string/pattern given to the _search_ subcommand contains sub-strings/patterns which match newlines, then it will be possible for that command to return a match which spans multiple lines. Where a match could occur both within a single line and across multiple lines, the first such match will be found, and the length of the match will follow the usual regexp rules, as documented in the regexp man page. Since the text widget is inherently a line-based container of text, regexp searches will implicitly use the regexp _-line_ functionality so that _^_, _$_ matching beginning and end of any line, and _._, _[^_ will not match a newline \(but see the _-nolinestop_ flag to turn off the latter behaviour\). This can be implemented very efficiently, given the _TCL\_REG\_CANMATCH_ flag supported by the regexp library, with no impact at all on the speed of matching single lines. In addition, two new options to the _search_ subcommand are available: If the new _-all_ option is given to the _search_ subcommand, then all matches within the given range will be reported. This means the return result of the command will be a list of indices, and, if a _-count var_ option was given, _var_ will be set to a list of match-index-lengths. If the new _-nolinestop_ option is given then regexp searches will allow _._ and _[^_ sequences to match newline characters \(which is normally not the case\). This is equivalent to _not_ providing the _-linestop_ flag to Tcl's _regexp_ command. The text widget man page will be updated to reflect the new _-all_ and _-nolinestop_ options, and to remove the "single line" caveat. # Reference implementation This is available from: <http://sourceforge.net/tracker/?func=detail&aid=621901&group\_id=12997&atid=312997> The patch includes objectification of the entire Text widget, so the multi-line search changes are not obvious to isolate. In fact the changes required are < 100 lines of code \(given that the rest has been objectified, that is\). Of course one nice side-effect of objectification is that regexp objects used in searches are actually cached, which they previously couldn't be. Note: this patch has to workaround a crashing bug in Tcl's unicode string manipulation. It would be best if that bug was fixed before applying this patch. # Issues On the implementation side, it might be interesting to abstract the search interface away from the text widget, so that it could in principle be applied to any line-based textual source. As in the single-line matching implementation in Tcl 8.x, the lack of support for backwards matching in Tcl's regexp library means that backwards matching can only be implemented as repeated forward matches, with a commensurate performance penalty \(the solution to which is outside the scope of this tip\). Tk has a curious misfeature that _$text search -regexp "\\n" $pos_ will always fail to match anything. This behaviour will change as a result of this TIP \(it will match the first newline after _$pos_\), and any code which somehow depended on that peculiarity will therefore break. # Copyright This document has been placed in the public domain. |
Name change from tip/114.tip to tip/114.md.
|
| < | | | | | | < | | | > | | | | | | | | < > | < > | < > | | | | | | | | | | | | | | | | | | < > | < > | | | | | | | | | | | | | | | < > | | | | | | | < | > | | | | | | | | | | > | 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 | # TIP 114: Eliminate Octal Parsing of Leading Zero Integer Strings Author: Don Porter <[email protected]> Created: 16-Oct-2007 Type: Project State: Draft Vote: Done Tcl-Version: 9.0 Post-History: Keywords: octal ----- # Abstract This TIP proposes elimination of Tcl's practice of using octal notation to interpret a string with a leading zero when an integer value is expected. # History and Rationale There are several places in the syntax of several Tcl commands where an integer value may be accepted. Routines such as **Tcl\_GetInt\(\)** perform the task of parsing an integer value from the string value in these places. Ultimately, these routines have been built on C standard library functions such as **strtol\(\)**. Due to this implementation choice, Tcl integer parsing has inherited features from **strtol\(\)** including the feature that a leading zero in a string has been taken as a signal that the string is an integer value in octal format. Several programmers and programs have hit this feature by surprise, resulting in nasty bugs such as: % proc m date { lassign [split $date -] y m d return [string index _JFMAMJJASOND $m] } % m 2007-02-14 F % m 2007-12-25 D % m 2007-09-26 bad index "09": must be integer?[+-]integer? or end?[+-]integer? (looks like invalid octal number) There are very few places in Tcl scripts where this feature is actually useful. Octal format for integers simply isn't encountered all that often in most programming tasks tackled by Tcl scripts. The main counterexample is the use of octal format integers to describe filesystem permissions on unix systems. The Tcl commands that operate on filesystem permission values are **open** and **file attributes**, and it is a simple matter to directly code them to recognize octal format, rather that have then rely on octal parsing as a general integer value recognition feature. On the HEAD, these commands have already been so revised. With those few cases accounted for, it's been observed that removing this feature of Tcl integer parsing "will likely fix more scripts than it breaks." The opportunity to make this change in Tcl 8.5 arises because we've already replaced our old parsing routines based on **strtol\(\)** with our own number parser [[249]](249.md). # Proposal Revise all integer parsing in Tcl by making modifications to the **TclParseNumber\(\)** routine. With reference to the state machine graph in [[249]](249.md), we change the exit edges of state _integer[[1]](1.md)_. Characters **0** - **7** and characters **8** - **9** should now lead to state _integer[[4]](4.md)_, so that they continue decimal parsing, and not octal parsing. The states _integer[[2]](2.md)_ and _error[[5]](5.md)_ will now be accessible only if the character **o** or **O** is seen while in state _integer[[1]](1.md)_ and there will no longer be any exit from those states when the characters **.** or **e** or **E** are observed. This change to **TclParseNumber\(\)** is achieved with a **\#define KILL\_OCTAL** in the file _tclStrToD.c_. # Compatibility This change is an incompatibility. It's long been believed that such a change should not happen until Tcl 9 because of this, but over time the consensus belief has developed that far fewer programs and programmers will be harmed by the incompatibility than will be helped by removing the misfeature. That said, the incompatibility is serious. The same string in the same place in a script can now have a completely different meaning. Before the change: % lindex {a b c d e f g h i j k} 010 i After the change: % lindex {a b c d e f g h i j k} 010 k This is not the usual situation where new feature causes scripts that were an error to become non-errors -- a compatible change. This is also not a situation where a change causes legal scripts to become errors. Such a change would break scripts, but would at least leave behind scripts that raise noisy errors alerting about the breakage. This is the most serious kind of incompatibility, where we replace a working script with another working script that does something completely different. An illustration of the problem from Tcl's own test suite highlights the danger. Some of Tcl's tests in **io.test** depend on the umask value, so that value is captured: set umaskValue [exec /bin/sh -c umask] Note that the shell command **umask** returns a mask value as an integer in octal format. The test suite has relied on Tcl's built-in ability to recognize this format, and the expected result of test **io-40.3** has been computed: format %04o [expr {0666 & ~$umaskValue}] After the proposed change, _$umaskValue_ is treated as a decimal number, and the wrong expected result is computed. \(This test has already been updated on the HEAD to avoid such problems.\) It is not difficult to imagine more serious problems in scripts that make use of the result returned by the shell command **umask** where a file might be created or modified with completely unintended permissions as a result of the proposed change. Such scripts might easily raise security concerns. Even in the light of the judgment that such \(hopefully rare\) compatibility issues are acceptable in exchange for the benefits of purging the misfeature, we really ought to consider seriously how we can alert those migrating to Tcl 8.5 to this possibility and to the need to examine their scripts for this issue. Besides the impact on Tcl commands, this change may also cause incompatibilities in extensions, to the extent their commands rely on Tcl's integer parsing to support octal notation. # Rejected Alternatives Motivated largely by the serious incompatibilities lurking here, a few people have suggested that some means be provided to toggle Tcl's integer parsing behavior between two modes, one which recognizes octal and one which does not. This idea appears inspired in part by the **::tcl\_precision** variable, which has long exercised control over Tcl's floating point number formatting. While the motivation may be well-intended, this proposal is basically unworkable, and can't really help anybody. The point of the proposed change is to make simple code work as simple coders expect it to. Our original example proc can already be corrected like so: proc m date { scan $date %d-%d-%d y m d return [string index _JFMAMJJASOND $m] } The point of this proposal is to make the original code just work. It doesn't help to offer this complexity as a solution: % proc m date { set mode [tcl::unsupported::octal] tcl::unsupported::octal off lassign [split $date -] y m d set result [string index _JFMAMJJASOND $m] tcl::unsupported::octal $mode return $result } No one would choose that over just fixing the code to use **scan**, in which case this proposal won't be needed. Also, this kind of management of a shared mode setting cannot \(easily and cheaply\) be avoided, because at the point we need to control the Tcl number parser, the most specific context we have is the thread, so the mode has to be set thread-wide. Likewise, the \(hopefully rare\) set of scripts that would actually want to turn octal parsing back on are not going to announce themselves. In order to know that tcl::unsupported::octal on needs to be added to a script to make it function correctly, some kind of audit has to reach that conclusion, and once that conclusion is reached and the issues are understood, it's just as easy to insert **scan %o** in the proper places as it would be to insert the **tcl::unsupported::octal** stopgap. In short, any coder finding themselves in a position to consider using a **tcl::unsupported::octal** tool, would quickly decide not to use it in favor of just fixing their code. Thus users of this feature are mythical, and it will not be implemented. # Note This TIP has been _explicitly_ rejected as a feature for Tcl 8.5. Consensus was that the type of breakage it inherently induces is not acceptable in a minor version change. # Copyright This document is placed in the public domain. |
Name change from tip/115.tip to tip/115.md.
|
| < | < | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 115: Making Tcl Truly 64-Bit Ready Author: Donal K. Fellows <[email protected]> State: Draft Type: Project Vote: Pending Created: 23-Oct-2002 Post-History: Tcl-Version: 9.0 ----- # Abstract This TIP proposes changes to Tcl to make it operate more effectively on 64-bit systems. # Rationale It is a fact of life that 64-bit platforms are becoming more common. While once the assumption that virtually everything was a 32-bit machine \(where not smaller\) was valid, this is no longer the case. Particularly on modern supercomputers \(though increasingly in workstations and high-end desktop systems too\), the amount of memory that the machine contains is exceeding 2GB, and the need to address very large amounts of memory is certainly there in scientific and engineering applications. And where they lead, consumer systems will probably follow too. At the moment, Tcl is ill-prepared for this. In particular, the type used for expressing sizes of entities in Tcl \(whether strings, lists or undifferentiated blocks of memory\) is _int_ \(and cannot be made into an _unsigned int_ in most of those places where it is not already an unsigned value\) but on the majority of 64-bit platforms this is still a 32-bit type, which is a major restriction. However, on the vast majority of those platforms _long_ is a 64-bit type, and so a suitable replacement. \(The exceptions to this are the Alpha - but that is unusual in that both _int_ and _long_ are 64-bit types there, meaning that the platform will be unaffected by such an alteration - and Win64, which has a 32-bit _long_ but 64-bit pointers.\) Luckily, standards like POSIX have already been dealing with this problem before us, and the types _size\_t_ \(which is unsigned\) and _ssize\_t_ \(which is signed\) exist for the sorts of uses we're interested in \(i.e. they are both the same size as each other, and _size\_t_ is large enough to describe the size of any allocatable memory chunk.\) # Details of Changes The key changes will be to change the lengths of the following types from _int_ to _ssize\_t_ in all appropriate places, and _unsigned int_ to _size\_t_ likewise \(mainly in memory allocation routines.\) * _Tcl\_Obj_ - the _length_ member. \(Potentially the _refCount_ member needs updating as well, but that's less critical.\) * _Tcl\_SavedResult_ - the _appendAvl_ and _appendUsed_ members. * _Tcl\_DString_ - the _length_ and _spaceAvl_ members. * _Tcl\_Token_ - the _size_ and _numComponents_ members. * _Tcl\_Parse_ - the _commentSize_, _commandSize_, numWords_, _numTokens_ and _tokensAvailable_ members. * _CompiledLocal_ - the _nameLength_ member. * _Interp_ - the _appendAvl_, _appendUsed_ and _termOffset_ members. * _List_ - the _maxElemCount_ and _elemCount_ members. * _ByteArray_ - the _used_ and _allocated_ members. * _SortElement_ - the _count_ member. * _SortInfo_ - the _index_ member. * _CopyState_ - the _toRead_ and _total_ members. * _GetsState_ - the _rawRead_, _bytesWrote_, _charsWrote_ and _totalChars_ members. * _ParseInfo_ - the _size_ member. * _String_ - the _numChars_ member \(see also the _TestString_ structure.\) Changes to the bytecode-related structures might be worthwhile doing too, though there are more backward-compatibility issues there. These changes will force many of the types used in the public API to change as well. Notable highlights: * _Tcl\_Alloc_ will now take an _size\_t_. * _Tcl\_GetByteArrayFromObj_ will now take a pointer to a _ssize\_t_. * _Tcl\_GetStringFromObj_ will now take a pointer to a _ssize\_t_. * _Tcl\_ListObjLength_ will now take a pointer to a _ssize\_t_. * _Tcl\_GetUnicodeFromObj_ will now take a pointer to a _ssize\_t_. In the internal API, the following notable change will happen: * _TclGetIntForIndex_ will now take a pointer to a _ssize\_t_. There are probably other similar API changes required. # What This TIP Does Not Do This TIP does not rearrange structure orderings. Although this would be very useful for some common structures \(notably _Tcl\_Obj_\) if the common arithmetic types were smaller than the word size, it turns out that the changes in types required to deal with larger entities will make these rearrangements largely unnecessary and/or pointless. \(Inefficiency in statically-allocated structures won't matter as the number of instances will remain comparatively small, even in very large programs.\) Once the changes are applied, there is typically at most a single _int_ field per structure, usually holding either a reference count, a set of flags, or a Tcl result code. It should also be noted that all structures are always going to be correctly aligned internally as we never use C's bitfield support, so structure alignment is purely an issue of efficiency, and not of correct access to the fields. # Copyright This document has been placed in the public domain. |
Name change from tip/116.tip to tip/116.md.
|
| < | < | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 116: More Safety for Large Images Author: Donal K. Fellows <[email protected]> State: Final Type: Project Vote: Done Created: 28-Oct-2002 Post-History: Tcl-Version: 8.5 ----- # Abstract This TIP alters the C API for Tk's images so that failures to allocate sufficient memory for a large image can be handled more gracefully than a straight _panic\(\)_. # Rationale Tk's image mechanism is nice and flexible, but it can run into problems with a large image. If we consider a square image that is 2000 pixels on each side \(such sizes of images are becoming more common with the increasing popularity and sophistication of digital photography\), we find it requires about 16MB of memory to load \(4 million pixels, four bytes per pixel\) but obviously just because an application fails to load that image \(or something even larger\), it doesn't mean that the best course of action is a _panic\(\)_-induced crash. Instead, a graceful failure back to the Tcl interpreter would allow for scripts to find a way to report this low-memory situation in a way that users can understand. The problem with this is that for many of the routes through the Tk image API, there is no way to report a memory allocation failure; currently, the only failure mode is total. This TIP changes this. # Proposed Changes I propose making the following functions that currently return _void_ return _int_ instead and that they should additionally take a standard _Tcl\_Interp \*interp_ argument to allow an error message describing the failure \(currently only due to insufficient memory\) to be added to the current interpreter. It will not be an error for the _interp_ argument to be _NULL_, though it will be up to the caller to guess why the failure happened. * _Tk\_PhotoExpand_ will become: int Tk_PhotoExpand(Tcl_Interp *interp, Tk_PhotoHandle handle, int width, int height) * _Tk\_PhotoPutBlock_ will become: int Tk_PhotoPutBlock(Tcl_Interp *interp, Tk_PhotoHandle handle, Tk_PhotoImageBlock *blockPtr, int x, int y, int width, int height, int compRule) * _Tk\_PhotoPutZoomedBlock_ will become: int Tk_PhotoPutZoomedBlock(Tcl_Interp *interp, Tk_PhotoHandle handle, Tk_PhotoImageBlock *blockPtr, int x, int y, int width, int height, int zoomX, int zoomY, int subsampleX, int subsampleY, int compRule) * _Tk\_PhotoSetSize_ will become: int Tk_PhotoSetSize(Tcl_Interp *interp, Tk_PhotoHandle handle, int width, int height) Also note that as a consequence of this, some image-related Tk commands will also gain additional error return situations. Since these all trigger abnormal process termination \(and potentially a core-dump too\) at the moment, this change in behaviour is believed to be wholly beneficial. # Backward Compatibility This TIP also proposes a backward compatibility interface, so that extensions need not be heavily modified to work with new versions of Tk. This is done by leaving backwardly-compatible functions in the old locations in Tk's stub table and adding a _\#define_ to allow selection of the old API with the standard names. I propose doing this when the symbol _USE\_PANIC\_ON\_PHOTO\_ALLOC\_FAILURE_ is defined; like this, extension authors can switch from compiling with Tk 8.4 to using later versions by adding just one flag to their makefile \(or other build script/environment.\) Note that this interacts with the backward-compatability interface defined in [[98]](98.md); if that is enabled, the back-compat interface defined here is enabled as well. # Sample Implementation <http://sf.net/tracker/?func=detail&aid=646382&group\_id=12997&atid=312997> # Copyright This document has been placed in the public domain. |
Name change from tip/117.tip to tip/117.md.
|
| < | < | | | | | | | | > | | | | | | | | | | | | | < > | | | < > | | | | | | | | | | | | < > | | | | | < > | | | | | | | | | | < > | | < | > | | > | 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 | # TIP 117: Object Type Introspection Author: Peter Spjuth <[email protected]> State: Withdrawn Type: Project Vote: Pending Created: 01-Nov-2002 Post-History: Tcl-Version: 8.5 Obsoleted-By: 214 ----- # Abstract This TIP proposes to add a command to give information on the current internal representation of an object. # Rationale When trying to understand the internals of objects and when trying to track down shimmering problems it is very helpful to be able to see what type an object currently has. # Specification A new package called "Debug" is created as part of the core. A new command, _objtype_, is added to the Debug package. The command has the syntax: > **Debug::objtype** ?_value_? If no value is submitted, a list of all currently registered object types are returned. If a value is submitted, it returns a list where the first element is the name of value's object type, or "none" if there is no internal representation. The second element is a boolean stating if the object has a valid string representation. Examples: % Debug::objtype boolean index double end-offset wideInt list cmdName bytecode nsName procbody bytearray int {array search} string % set apa hejsan hejsan % Debug::objtype $apa none 1 % string length $apa 6 % Debug::objtype $apa string 1 % regexp $apa hoppsan 0 % Debug::objtype $apa regexp 1 % Debug::objtype [expr 1+1] int 0 # Discussion The first proposal was to add this as a subcommand to info. This was considered bad since this should be a pure debug command and should never be used in live code. Thus the proposition came up to create a Debug package and put it in there to emphasise its debug nature. The Debug package can also be extended in the future with other utilities. # Reference Implementation static int ObjTypeCmd(dummy, interp, objc, objv) ClientData dummy; /* Not used. */ Tcl_Interp *interp; /* Current interpreter. */ int objc; /* Number of arguments. */ Tcl_Obj *CONST objv[]; /* Argument objects. */ { Tcl_Obj *listPtr; if ((objc != 2) && (objc != 3)) { Tcl_WrongNumArgs(interp, 2, objv, "?value?"); return TCL_ERROR; } listPtr = Tcl_NewListObj(0, (Tcl_Obj **) NULL); if (objc == 2) { Tcl_AppendAllObjTypes(interp, listPtr); } else { Tcl_ListObjAppendElement(interp, listPtr, Tcl_NewStringObj( (objv[2]->typePtr != NULL) ? objv[2]->typePtr->name : "none", -1)); Tcl_ListObjAppendElement(interp, listPtr, Tcl_NewBooleanObj(objv[2]->bytes != NULL)); } Tcl_SetObjResult(interp, listPtr); return TCL_OK; } # Future possibilities For further object introspection the command can easily be extended by options. # Copyright This document has been placed in the public domain. |
Name change from tip/118.tip to tip/118.md.
|
| < | < | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 118: Enhance [file attributes] and [file copy] on Mac OS X & BSD Author: Daniel A. Steffen <[email protected]> State: Final Type: Project Vote: Done Created: 01-Nov-2002 Post-History: Tcl-Version: 8.5 ----- # Abstract This TIP proposes a set of changes to _[file attributes]_ and _[file copy]_ to make them function better on MacOS X and other BSD-Unix systems. # Summary of Proposed Changes This TIP proposes five sets of changes to _[file attributes]_ and _[file copy]_: 1. Add support for the Macintosh and Windows specific flag _[file attributes -readonly]_ to Unixes that support the _chflags\(\)_ API, to allow the _user immutable_ flag to be accessed & modified from Tcl. 2. Add support for the Macintosh specific flags _[file attributes -readonly -creator -type -hidden]_ to Mac OS X via the POSIX level API _getattrlist\(\)_. 3. Add a new flag _[file attributes -rsrclength]_ to Mac OS X and Mac OS 9 that gives the length of the resource fork of a file; 0 is the only value that this attribute can be set to, which strips the resource fork off a file. 4. Change _[file attributes]_ to return the list of attributes that can be retrieved without error for a given file, instead of aborting the whole command when any error occurs. 5. Enhance _[file copy]_ on Mac OS X \(more precisely, the native file-system _Tcl\_FSCopyFile_\) to copy finder attributes \(i.e. _-readonly -creator -type -hidden_\) and resource forks transparently. # Rationale There is currently no way to access and modify HFS file-system metadata from Tcl on Mac OS X whereas Tcl on Mac OS 9 \(or Classic\) on the same Macintosh has that capability. Worse, _[file copy]_ \(and potentially even _[file rename]_ if it results in a copy\) on Mac OS X can be a destructive operation at present if it operates on a file that has essential data in its resource fork or its HFS metadata. This again in contrast to the same operations in Tcl on Mac OS 9 where this information is preserved. This TIP seeks to rectify these asymmetries in order to better hide such file-system related platform specificities from the scripter. # Details Additional information & examples: 1. Unix versions that support _chflags\(\)_ include BSD >= 4.4 and Darwin/Mac OS X \(where _user immutable_ is the flag corresponding to the file locked state on the HFS file-system, which is what _[file attributes -readonly]_ controls on Mac OS 9\). 2. The use of _getattrlist\(\)_ does not require linking with Carbon and thus allows access to HFS file-system metadata from Tcl on pure open-source Darwin systems \(which is something no other scripting language can claim at present\). 3. The new attribute _-rsrclength_ is useful to check whether a file has a resource fork and to calculate total file size on Mac OS 9 and X \(note that _[file size]_ returns the size of the data fork only\). Stripping a file's resource fork \(by setting _-rsrclength_ to 0\) is a common operation on Mac OS when dealing with files that are destined for other platforms. This is a feature that has been requested several times and given that it ties in well with the implementation of the other new attributes it comes at essentially no additional cost. % file attributes test -group admin -owner steffen -permissions 00644 -readonly 0 -creator Doug -type RSRC -hidden 0 -rsrclength 314 % file attributes test -rsrclength 5 setting nonzero rsrclength not supported % file attributes test -rsrclength 0 % file attributes test -group admin -owner steffen -permissions 00644 -readonly 0 -creator Doug -type RSRC -hidden 0 -rsrclength 0 4. On Mac OS X, trying to retrieve the new attributes _-creator -type -rsrclength_ fails on non-regular files & directories \(and on any file located on a non-HFS file-system that doesn't support _getattrlist\(\)_\). Returning only the list of attributes that are valid seems like much more sensible behaviour in this case than failing with an error and not returning anything. In the case where no valid attributes can be retrieved at all, the error returned by the last attempt is passed upstream, to preserve existing error handling. This proposed change in behaviour of _[file attributes]_ seems necessary to allow the command to continue to work in a consistent way on all inputs and on all platforms; it should not impact existing code since for current attributes, failure to retrieve any one attribute is equivalent to failure to retrieve all attributes. % close [open test w] % file attributes test -group admin -owner steffen -permissions 00644 -readonly 0 -creator {} -type {} -hidden 0 -rsrclength 0 % file delete test % file mkdir test % file attributes test -group admin -owner steffen -permissions 040755 -readonly 0 -hidden 0 % file delete test 5. Unlike the Finder and other HFS aware tools on Mac OS X, Tcl currently ignores HFS metadata and the resource fork, which will undoubtedly surprise scripters unpleasantly. _[file copy]_ should hide such platform specificities and copy a file in the same way as the Finder: % file attributes test -group admin -owner steffen -permissions 00644 -readonly 0 -creator Doug -type RSRC -hidden 0 -rsrclength 314 % file copy test test1 % file attributes test1 -group admin -owner steffen -permissions 00644 -readonly 0 -creator Doug -type RSRC -hidden 0 -rsrclength 314 % file delete test1 # Comments Additional implementation details: * To support the new attributes _-creator -type_, routines to convert from numerical OSTypes \(_u\_int32\_t_\) to the usual four character human readable format have been adapted from _mac/tclMacResource.c_; the new versions accept/return strings of length 0-4 unlike the originals that only dealt with length 4. This is important because creator/type 0 \(i.e. _-creator \{\} -type \{\}_\) is common on Mac OS X. The Mac OS 9 implementation of the OSType string representation code has been modified accordingly by adding support for strings of length 0-4 and missing _UtfToExternal/ExternalToUtf_ conversions. * _macRoman_ is the encoding used for the string representation of OSTypes, for consistency with Tcl on Mac OS 9 as well as with common Mac OS X tools such as Resorcerer & SuperGetInfo that all use _macRoman_ to display creator/type codes; this encoding is probably what most people would expect. It's unfortunate that this means that use of _[file attributes]_ on Darwin/Mac OS X will cause the non-builtin _macRoman_ encoding to load. ASCII-only OSTypes will still work properly if _macRoman_ is not available, fallback to _latin1_ in that case could also be added if deemed necessary. However, the Tk Aqua port already relies on _macRoman_ being present so in the most common usage pattern _macRoman_ should be present and loaded anyway. * The Mac OS 9 implementation of _[file attributes -creator -type]_ currently returns the bogus 'Fldr' type & creator for directories, this has been changed to return an error for consistency with the Mac OS X implementation. * Most of the implementation of the new Mac OS X specific features has been added added at the end of _unix/tclUnixFCmd.c_, it might be cleaner to move this code to a separate file _macosx/tclMacOSXFCmd.c_, but that would require several routines in both _unix/tclUnixFCmd.c_ and _mac/tclMacOSXFCmd.c_ to be made non-static. It's unclear whether this is an acceptable change just for the sake of code separation/cleanliness. # Reference Implementation SourceForge patch \#626360 <http://sourceforge.net/tracker/index.php?func=detail&aid=626360&group_id=10894&atid=310894> implements this TIP as a patch to the current HEAD. The patch has been tested on the SF compile-farm on hosts: [Alpha] Linux 2.4 \(Debian 3.0\): where _chflags\(\)_ and _getattrlist\(\)_ are not available and no ill effects ensue \(i.e. no new tests fail\). [x86] FreeBSD \(4.7-RC\): where _chflags\(\)_ is available and _[file attributes -readonly]_ can successfully be interrogated \(but not set due to permission issues at SourceForge\). No new tests fail. as well as on Mac OS 9, X 10.1.5 and X 10.2.1, where all the new functionality is available and no new tests fail. # Copyright This document has been placed in the public domain. |
Name change from tip/119.tip to tip/119.md.
|
| < | < | | | | | | | | > | | | | | | | | | | | | | | | | | | > | 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 | # TIP 119: Angled Text on a Canvas Author: Simon Geard <[email protected]> Author: Donal K. Fellows <[email protected]> State: Final Type: Project Vote: Done Created: 18-Nov-2002 Post-History: Tcl-Version: 8.6 ----- # Abstract The current text object on a canvas does not support the creation of text strings at an arbitrary angle. For some applications this is limitation is sufficiently serious to disqualify Tk from use. This TIP removes this restriction. # Rationale Using a Tk canvas to display e.g. an engineering drawing from a CAD application is limited - such applications will output angled text and there is simply no way of displaying such text on a canvas. Another consideration is the competition. Both Qt and Java canvas objects support angled text on their canvas object - most new users would I believe be surprised to discover that this functionality is not supported. Due to the internal architecture of Tk a side effect of this work would be to enable buttons \(and possibly other widgets\) to have their text written at an angle as well. This TIP does not expose that functionality. # Implementation At the command level there would be an extra attribute, _-angle_, added to the canvas's text object: <canvas> create text <x> <y> -text <str> ?-angle <angle>? ... where the angle is specified in degrees. Manipulation of the angle would be done in the usual way through the _itemconfigure_ and _itemcget_ subcommands: <canvas> itemconfigure <tag> -angle <angle> Note that PostScript naturally supports rotation of text. # Reference Implementation I have done an initial assessment of the amount of work required and have and have created a patch to implement it in Tk 8.4.5 . This initial work was fairly straightforward but the internal housekeeping work maintaining and interacting with an angled box will be more substantial. The patch \(uploaded to SourceForge <http://sf.net/tracker/?func=detail&aid=1611359&group_id=12997&atid=312997> \) is for X only. It doesn't use any X extensions and should work for X11R3 and above. I don't know how it would be done on non-X systems but hopefully they'll \(Win & MacOS at least\) provide native tools to make their implementation straightforward as well. ## Implementation Notes The implementation was tricky to develop, because it was wholly different on each rendering platform \(X11 is two, depending on which font rendering engine is used\). This delayed implementation of this TIP for a whole release. Classic X11: Uses a general monochrome pixmap rotation engine. X11 \+ Xft: Generates rotated versions of the fonts by installing a rotation matrix, caching them in the subfont management engine. Win32: Generates rotated versions of the fonts using the built-in font rotation suport, caching them in the subfont management engine. MacOS X: Applies the rotation to the Current Transformation Matrix immediately before rendering. # Copyright This document has been placed in the public domain. |
Name change from tip/12.tip to tip/12.md.
|
| < | < | | | | | | | | > | | | | | | | | 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 | # TIP 12: The "Batteries Included" Distribution Author: George A. Howlett <[email protected]> Author: Larry W. Virden <[email protected]> State: Draft Type: Informative Vote: Pending Created: 15-Sep-2000 Post-History: Discussions-To: news:comp.lang.tcl ----- # Abstract This document describes a comprehensive Tcl/Tk distribution. Its primary purpose is to create a standard source tree that includes Tcl, Tk, and extensions so that they can be built and installed in an simple and easy manner. # Introduction One of the most enduring complaints about Tcl/Tk is that it lacks features, especially when compared to Perl, Python, or Java. We patiently explain that some particular feature is available in extension "XYZ" only to hear how hard it is to build and install extensions. Frank Stajano \("The SMS server, or why I switched from Tcl to Python"\) describes the problem succinctly. > "But if I had to put the finger on the single most important reason that has me now working in Python rather than in Tcl/[incr Tcl] it would not be a language issue but a library issue. I prefer Python because its standard library is a gold mine. Sure, for anything I want to do there's bound to be an extension available in the Tcl code repository on the FTP site. Now I just have to find it, fetch it, recompile the interpreter with it \(Oh wait - this may mean getting and installing a C compiler for this system. Will the GNU one compile the windowing stuff properly or do I need to get VC\+\+, or Borland? Who wants to have some fun discovering where another IDE has hidden the useful compiler flags this week?\), hope that it won't clash with other extensions I've had to install, hope that it will not require a different version of the interpreter from the one I am running, and so on. Python supports the same C extension mechanism as Tcl - but the practical difference is that the stuff I want is, most of the time, already included and shipped in the standard distribution of the language!" |
︙ | ︙ | |||
64 65 66 67 68 69 70 | that words "core" and "extension" disappear from our Tcl vocabularies. We've lived their artifical distinctions that are useful only to core developers and extension writers. It's skewed our thinking about relationship between Tcl and its parts. After all, application writers first care about whether a feature or capability is available, not how it's structured under the hood. | | | | | | | | | | | | | | | | 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 | that words "core" and "extension" disappear from our Tcl vocabularies. We've lived their artifical distinctions that are useful only to core developers and extension writers. It's skewed our thinking about relationship between Tcl and its parts. After all, application writers first care about whether a feature or capability is available, not how it's structured under the hood. # The "Batteries Included" Distribution. Let's start with a very modest example. Let's imagine that the "Batteries Included" distribution is nothing more than an archive file of the source code for Tcl/Tk and several extensions. Unix Windows Mac ---- ------- --- Tcl 8.3 x x x Tk 8.3 x x x [incr Tcl] x x x expect x ? TclX x BLT x x Trf Html widget XML ...lots more... Tcl, Tk, and the packages are configured such that they can be built and installed just from a top level directory \(not individually\). Someone can download and try out all sorts of new features without repeating the same "configure", "make", "make install" sequences. With this simple tar file, the following benefits are automatically generated: * It provides a simple way for users to try out extensions. Users |
︙ | ︙ | |||
108 109 110 111 112 113 114 | features being universally available. Your program can again be just a Tcl script, not an array of packages that everyone needs to download and install. * It's better for extension writers. Configuration is simpler, since you know where all the sources and the compiler-specific information will reside. You don't need to search for | | | | | | 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 | features being universally available. Your program can again be just a Tcl script, not an array of packages that everyone needs to download and install. * It's better for extension writers. Configuration is simpler, since you know where all the sources and the compiler-specific information will reside. You don't need to search for _tclConfig.sh_ or _tkConfig.sh_ files. * It's better for Tcl/Tk distribution builders. This includes both the Linux distributors and company sysadmins that build Tcl/Tk. They don't have to fear installing extensions because of version dependencies. > Let's give Redhat and SuSE a good reason to move off of version 8.0. One the big advantages of Linux over \(let's say\) Solaris is that each new Redhat or SuSE distribution comes with updated versions of utilities already built. * It's better for the core developers. Extension writers will willing the adopt changes in exchange for the wider distribution. The core team will in turn gain better understanding of the burdens of extension writers. * It's better for Tcl library writers. With [incr Tcl], we now have a basis for a real, extensible Tcl-code library. Library code rely on a full set of extensions being available. # Rationale We want to create an open door procedure that makes it easy for contributors to add new features and commands to Tcl and Tk. By creating a framework for extensions to be built and distributed, the "Batteries Included" distribution will provide a path for great new features to quickly become available to the Tcl community. |
︙ | ︙ | |||
157 158 159 160 161 162 163 | If the "Batteries Included" distribution is to become successful, it must be a cooperative effort between Tcl core developers, extension writers, and the Tcl user community. For example, we need the help of extension writers to adopt the new configuration scheme and directory structure. | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 | If the "Batteries Included" distribution is to become successful, it must be a cooperative effort between Tcl core developers, extension writers, and the Tcl user community. For example, we need the help of extension writers to adopt the new configuration scheme and directory structure. # Particulars We can stage the project with small milestones while still focusing on longer range goals. For example, the first phase can be as simple as creating a tar file. It will start to address questions that were raised by TEA. For example, how do we manage documentation? The biggest reason why this proposal will succeed is the incredible talent in the Tcl community. We can leverage the skills and experiences of the foremost experts on the core, extensions, and applications. # Tcl/Tk Version. The distribution will be based on 8.3.2 \(or 8.3.3 when it is released\). While there's no assurance when 8.4 will be released and in what state, we also want to place a premium on stable, robust extensions, that have been thoroughly tested. Most extensions will be unlikely to have been tested against the 8.4 alphas. # Phase 1. * Identify extensions. > What extensions should be included in the near term? We need extension authors that are willing to work with us to build a directory framework, change configuration files, etc. Extensions do not need to work on all platforms. For example, there is a wealth of Windows-based extensions that should be included in a Windows specific build. > What are the minimum requirements for extensions in the short term? Manual pages, html, tests, demos all would be nice. We need to temper this with what's practical. This is a learning process. We can adjust requirements in future phases. * Determine build and install directory structures. > We need to make this work with more that one release installed. Don't suppose that there only one version will ever be used. * Setup CVS archives. * Create configuration files. > This will require negotiation with extension writers. We want their buy-in so they will maintain the changes. > There may be more than one form of configuration required. One subtle but important issue is that extensions must be able to be configured without Tcl or Tk libraries already existing. This is a "trusted" configure. The extension must trust that the library will exist. Right now, most extensions work from "untrusted" configurations. * Test builds on multiple platforms. > For now, the Windows and Mac build files can be hand-generated. It may be too hard to create a seamless build environment. We're not trying to satisfy every Windows/Mac developer here. We can focus on creating pre-built binary distributions for these platforms. * Create self-installing executables for Windows and the Mac. > If we want, we can provide Linux, Solaris, etc. binaries by reviving Michael McLennan's Tclish installer. # Phase 2. * Handle documentation issues. > Generate platform specific doc with Richard Hipp's XML code. * Establish Tcl code library. * Identify more extensions. * Determine the release schedule for "batteries included" distribution. > How often do you release a new version? It must be more frequent than Tcl/Tk. We can start by planning for quarterly releases and then adding more frequent releases if necessary. * Determine what core changes \(if any\) are needed for the distribution. * Start looking at network-based updates. * Start looking at selective builds. Allow builders to compile/install subsets of the distribution. * Push on Redhat, SuSE, etc. to pick up distribution. # Phase 3. * Network-based installs. * Selective installations/builds. * Include applications tree. * Identify more extensions. The last phases are sketchy. Feel free to add to this list, further breaking down goals into subtasks. # Open Issues * Windows and MacIntosh sources. > Given the dearth of configuration tools for these platforms, it's likely that only binary installations will be available for the near term. * Documentation > Overlap in command and widget names can be neatly handled by namespaces. Need to consider how to handle manual pages. # More Information If anyone has interest to participate or would like to add comments to the "Batteries Included" proposal, please send mail to George Howlett <[email protected]>. # Copyright This document has been placed in the public domain. # See Also [[4]](4.md) by Brent Welch <[email protected]>. |
Name change from tip/120.tip to tip/120.md.
|
| < | < | | | | | | | > | | | | | | | | | | | | | | | | < < | > > | | | | | | | | | | | | | | | | | | < < > > | | | | | | | | | | | > | 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 | # TIP 120: Restricted DDE Services Author: Pat Thoyts <[email protected]> State: Final Type: Project Vote: Done Created: 04-Dec-2002 Post-History: Tcl-Version: 8.5 ----- # Abstract This TIP will enhance the DDE package for use with safe interpreters and allow programmer control of the commands exposed by the DDE service. # Rationale By default the Tcl DDE service exposes all of the commands and variables available in the interpreter to all DDE clients. This is not always desirable. One solution might be to load the package into a safe slave interpreter and use [interp alias] to expose the required commands. Unfortunately the package doesn't support loading into safe interpreters. # Proposed Changes Firstly, this TIP proposes a _-handler_ option to the [dde servername] sub-command. The argument for this option should be the name of a procedure that will authenticate and evaluate DDE requests. Secondly, the DDE package should be enhanced to be capable of providing a service within a safe interpreter. # New Option The new syntax will be _dde servername ?-handler command? servername_. To permit introspection we will accept _dde servername -handler_ which will return the handler name \(if any\). If a servername must be defined using an initial hyphen then the standard '--' separator can be used. The dde request is appended to the handler command \(which may be a list\) and then evaluated in the global context. This ensures that all unsafe elements will not be evaluated before the handler code has a chance to examine them. So proc handler {request} { if {[string match "info *" $request} { uplevel #0 [lindex $request 0] [lrange $request 1 end] } else return -code error "permission denied" } } The above handler will permit [info vars] but will fail when trying [info vars ; bad_proc] with info complaining about the wrong number of parameters. Passing a single string means that we can handle standard dde styles of requests, for instance 'Open\("c:\\Program Files\\prog.exe"\)' which would not usefully convert into a list. # Safe DDE The dde package should support loading within a safe interpreter but with the following constraints. * The dde command should be hidden. This means that the safe interpreter may not call the command but a master interpreter call this command within the context of the safe interpreter. * Remote execution requests should be handled _only_ by a defined handler procedure. The normal default is to evaluate a remote execution request in the global namespace. I propose that when operating in a safe interpreter that the request be denied unless a handler is defined. The programmer then has the ability to authenticate the request before it is evaluated. * Remote variable reads should be denied. Rather that add in another handler - the XTYP\_REQUEST service command should be denied for safe interpreters. It is trivial to use [dde eval Remote set $varname] to read the value of a variable. # Reference Implementation See the SourceForge Feature Request at <https://sourceforge.net/tracker/index.php?func=detail&aid=649859&group\_id=10894&atid=310894> # Example # Provide a handler that only allows the [info] command # Note: This runs in the master interp. proc restricted_handler {request} { if {[string match "info *" $request} { uplevel #0 [lindex $request 0] [lrange $request 1 end] } else return -code error "permission denied" } } # Create a safe slave interpreter and expose as a DDE service. safe::interpCreate slave slave invokehidden load tcldde12d.dll Dde slave invokehidden dde servername -handler dde_cmd SafeSlave interp alias slave dde_cmd {} restricted_handler # If testing in tclsh... set ::_waiting 0 ; after 20000 {set ::_waiting 1} ; vwait ::_waiting # Consequences There should be no change to current users of this package unless they are using a server name beginning with a hyphen. In this case they will need to insert '--' before the server name. # Copyright This document is hereby placed in the public domain. |
Name change from tip/121.tip to tip/121.md.
|
| < | < | | | | | | | > | | | | | | | | | | | | | | | | | | | | | < > | | | | | | | | < | > | | | | | < > | | | | | | | | | | | | | | | < > | | < | > | | < > | | | | | | < > | | | | | | | | | | | | | | | | | > | 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 | # TIP 121: Controlled Application Shutdown via Tcl_Exit Author: Joe Mistachkin <[email protected]> State: Final Type: Project Vote: Done Created: 05-Dec-2002 Post-History: Tcl-Version: 8.5 ----- # Abstract This TIP will allow all applications to perform a controlled shutdown \(or do nothing\) in the event that _Tcl\_Exit\(\)_ is called. # Rationale For most applications written in C that use Tcl, calling the runtime _exit\(\)_ function is normally a reasonable way to shutdown the application. Unfortunately, this is not always the case. Applications written in other languages \(and very complex C applications\) may have very specific application shutdown requirements. This is especially true in multi-threaded environments. The problem is further compounded by extensions that use _Tcl\_Exit_. # Versus Exit Handlers There are distinct advantages to using this method instead of using normal exit handlers in some cases. The normal exit handler cannot defer \(or in an emergency, prevent\) the application shutdown because _Tcl\_Finalize\(\)_ has already been called. From the perspective of the exit handler, we have no way of knowing what other exit handlers have been called and/or their subsystems destroyed. In addition, even if it could somehow cause _Tcl\_Finalize\(\)_ to defer the application shutdown, some or all of the other exit handlers may have already been executed, which would leave the application in an inconsistent state. This relatively simple change allows the programmer to get control very early during the application shutdown process. # Proposed Changes First, this TIP proposes a new Tcl API function called _Tcl\_SetExitProc\(\)_ or something similar. This function accepts a _Tcl\_ExitProc_ pointer and returns a _Tcl\_ExitProc_ pointer. The return value is the old exit proc pointer. Second, the _Tcl\_Exit\(\)_ Tcl API function would be modified to allow for the handler to be called. Third, the documentation for _Tcl\_Exit\(\)_ would be updated to include _Tcl\_SetExitProc\(\)_ and a warning that any custom exit proc should NOT return. # Tcl\_SetExitProc Tcl_ExitProc * Tcl_SetExitProc(proc) Tcl_ExitProc *proc; /* new exit handler for app or NULL */ { Tcl_ExitProc *prevExitProc; /* return prev exit handler to caller */ Tcl_MutexLock(&exitMutex); prevExitProc = appExitPtr; /* get old app exit ptr */ appExitPtr = proc; /* set new app exit ptr */ Tcl_MutexUnlock(&exitMutex); return prevExitProc; } # Tcl\_Exit void Tcl_Exit(status) int status; /* Exit status for application; typically * 0 for normal return, 1 for error return. */ { Tcl_ExitProc *currentAppExitPtr; Tcl_MutexLock(&exitMutex); currentAppExitPtr = appExitPtr; Tcl_MutexUnlock(&exitMutex); if (currentAppExitPtr) { /***********************************************************/ /* WARNING: This code SHOULD NOT return, as there is code */ /* that depends on Tcl_Exit never returning. */ /***********************************************************/ currentAppExitPtr((ClientData) status); } else { Tcl_Finalize(); TclpExit(status); } Tcl_Panic ("exitProc returned!"); } # Example void MyAppExitProc(ClientData clientData) { /* #1. Perform application specific shutdown code... */ /* #2. Wait for other threads to gracefully shutdown... */ exit(0); return; /* We should never get here. */ } ... sometime during application initialization ... /* from this point on MyAppExitProc will handle Tcl_Exit requests */ Tcl_SetExitProc(MyAppExitProc); ... optionally, sometime later ... /* from this point on the old (default) handling will be used */ Tcl_SetExitProc(NULL); # Reference Implementation A patch that implements everything suggested in this TIP is available at the URL: <http://sourceforge.net/tracker/index.php?func=detail&aid=649313&group\_id=10894&atid=310894> # Consequences There is no change for current users of the _Tcl\_Exit\(\)_ function, including the [exit] command, if _Tcl\_SetExitProc\(\)_ is never called explicitly by the application. # Copyright This document is hereby placed in the public domain. |
Name change from tip/122.tip to tip/122.md.
|
| < | < | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 122: Use tcl_{non,}wordchars Throughout Tcl/Tk Author: Martin Weber <[email protected]> Author: Vince Darley <[email protected]> State: Rejected Type: Project Vote: Done Created: 12-Dec-2002 Post-History: Tcl-Version: 8.6 ----- # Abstract This TIP shall bring flexible management of word and non-word chars to Tcl, to be used throughout the Tcl realm in e.g. [regexp]'s \\w \\W, Tk's [textwidget], [string] wordstart/wordend etc. # Specification Assignment to _tcl\_\{non,\}wordchars_ shall influence any place in Tcl which decides whether something is a word character or not, including detection of word boundaries in e.g. regular expressions, Tk's text widget and so on. For this there shall be no hard-coding of lists of values which are word and non-word characters, and neither shall the language rely on the language of implementation \(i.e. C's _is\*\(\)_ functions\), as this disallows dynamic changing of _tcl\_\{non,\}wordchars_. Rather shall the value\(s\) of _tcl\_\{non,\}wordchars_ be used to determine whether a given character is part of a word or not. # Rationale Currently in Tcl there are different hard-coded ways to decide whether a certain character is a word character or a non word character. Different hard-coded ways also imply that changes on one side might not get over to the other side, so there soon are different hard-coded ways which yield different hard-coded results. As a inference of it being hard-coded, this also means that there is no way to change or fix that potentially broken behavior. Having Tcl lookup the values of those variables at runtime allows for the needed flexibility, both when dealing with nonstandard demands and nonstandard character sets. As an example of the breakage, you can assign a regular expression to tcl\_\{,non\}wordchars, and the double click binding in the textwidget will regard that pattern when marking a "whole word". When you try to ask the text widget to deliver the data under a certain coordinate with the indices 'wortstart' and 'wordend', the value of tcl\_\{non,\}wordchars is not used though. There may be a problem with the performance of the lookup, but on the other hand are C's _is\*\(\)_ functions also implemented via a table lookup. An installation of a caching static character table could guarantee the needed performance. # Example of current word confusion Tk's text widget uses "word" in several ways: 1. selection by word \(double-click \+ drag\), 2. movement by word \('insert wordstart'\), 3. regexp searching with \\m\\M wordmatching. 4. line breaks when wrapping \(-wrap word\) It is not at all clear from reading Tcl or Tk's documentation what the behaviour of the above options will be. It turns out that: 1. after a convoluted call-chain, ends up calling tcl\_wordBreakAfter/Before which use tcl\_wordchars and tcl\_nonwordchars \(which actually are defined differently on Windows vs Unix/MacOS!!\). 2. uses 'isalnum\(char\)' or '\_' to define a word \(hard-coded in Tk's tkTextIndex.c\) \(in Tk8.5a0 this has been fixed to use _Tcl\_UniCharIsWordChar_\) 3. uses Tcl's regexp engine's definition of a word \(this ought to be the same as that used in \(2\)\). 4. Anything separated by white-space from something else, used with '-wrap word' to define line-wrapping in text widgets \(and canvases\). It is quite likely that most of the above are different under some circumstances or some platforms/locales, and certainly if the user/developer wants to create a text widget with a different word definition, they basically can't in any consistent way. # Implementation None yet. # Copyright This document is placed in the public domain. |
Name change from tip/123.tip to tip/123.md.
|
| < | < | | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 123: Adding an Exponentiation Operator to the [expr] Command Author: Arjen Markus <[email protected]> Author: Donal K. Fellows <[email protected]> State: Final Type: Project Vote: Done Created: 16-Dec-2002 Post-History: Keywords: mathematics,evaluation Tcl-Version: 8.5 ----- # Abstract This TIP proposes to add a new operator to the operators recognised by the [expr] command: the exponentiation operator. This operator will enhance the functionality of the current _pow\(\)_ function by returning a result that depends on the type of its operands. It will also make complicated formulae more readable. # Introduction Currently Tcl's [expr] command uses the exponentiation function _pow\(\)_ to calculate such expressions as "2 to the power 10". The drawback of this is twofold: * Expressions using several exponentiations become difficult to read. For instance, a third-degree polynomial looks like: 2.0*pow($x,3) - 1.2*pow($x,2) + 3.0*$x + 4.0 > or: 2.0*$x*$x*$x - 1.2*$x*$x + 3.0*$x + 4.0 * The result of raising an integer to an integer power is a double: 2 to the power 10 is 1024.0, not 1024. Other languages, like for instance FORTRAN, use an operator instead of a function. Two operators are commonly found: \*\* and ^. As the latter already has a meaning within the [expr] command, we propose to add the "\*\*" operator instead. The above example would become: 2.0*$x**3 - 1.2*$x**2 + 3.0*$x + 4.0 # Mathematical Details The implementation of the exponentiation operator will have the following properties \(below we refer to the expression _$x\*\*$y_\): If _x_ and _y_ are both integers \(ordinary or wide\): * The result is of the same type as the widest operand * An error is raised if the operation makes no mathematical sense, _0\*\*\(-1\)_ for instance. * If _x_ has the value 0, then: > \* if _y > 0_, the result is 0 > \* if _y < 0_, the result is an error > \* if _y == 0_, the result is 1 * If _x_ has the value 1, then the result is always 1 * If _y_ has the value 0, the result is always 1 * If _x_ has a negative value lower than -1 and _y < 0_, the result is 0 * If _x_ has the value -1, then depending on whether _y_ is even or odd, the result is 1 or -1 \(respectively.\) * For all other combinations, the value is "_x_ raised to the power _y_" * When evaluating this, no attention is paid to overflow, even though the result might fit into a wide integer \(though of course the result will be a wide integer if either operand was wide.\) This is in accordance with the type model used in other [expr] operators. If either _x_ or _y_ is a double, the C function _pow\(\)_ is used to compute the result. The following expressions are parsed and evaluated in accordance with all other operators: $x ** $y ** $z ==> ($x ** $y ) ** $z $x ** -1 ==> ($x ** (-1)) The precedence of the exponentiation operator is thus _higher_ than the multiplication, division and remainder operations and lower than the unary operations, in accordance with common definitions. # Sample Implementation <http://sf.net/tracker/?func=detail&aid=655176&group\_id=10894&atid=310894> # Copyright This document is placed in the public domain. |
Name change from tip/124.tip to tip/124.md.
|
| < | < | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 124: High-Resolution Absolute Time Values From [clock] Author: Mark Harrison <[email protected]> Author: Kevin Kenny <[email protected]> State: Final Type: Project Vote: Done Created: 20-Dec-2002 Post-History: Tcl-Version: 8.5 ----- # Abstract This TIP proposes altering the **clock clicks** command to add a **-microseconds** option, and to tie it to an absolute reference. # Rationale The **clock clicks** command is a useful feature for analyzing and tuning performance in Tcl programs. Since the timer is relative, however, it is difficult to correlate times between two programs or with timestamps stored in a log file. # Proposed change This TIP proposes two changes to **clock clicks** to make it more useful in situations where absolute times are needed: 1. Change **clock clicks -milliseconds** to return a wide integer, representing the number of milliseconds since the Posix epoch. 1. Add a **clock clicks -microseconds** that likewise returns a wide integer, representing the number of microseconds since the Posix epoch. # Compatibility with existing code Now that Tcl supports 64-bit integers transparently, compatibility with existing code is unlikely to cause trouble. In practice, the only uses of **clock clicks** that the authors have seen all simply compute the difference between two successive values. Since the difference will continue to fit in 32 bits if it did so before, such code will simply continue to work. The change from a relative standard to an absolute one is likewise transparent. One fact that supports this claim is that such a change was made in **clock clicks -milliseconds** on Windows in support of [[7]](7.md), and no Windows users reported trouble as a result. Code that attempts to use **clock clicks_ as an absolute standard by correlating its values with those returned from **clock seconds** \(as in <http://wiki.tcl.tk/1035\)> will also continue to work without without change, although the improvements to **clock clicks** will certainly provide a better way to do it. # Reference Implementation The original reference implementation at <http://sf.net/tracker/?func=detail&atid=310894&aid=656997&group\_id=10894> presents an interface that has since been superseded. The reference implementation will be updated at such time as this TIP is approved. # Copyright This document has been placed in the public domain. # Comments Gerald Lester also points out \(in the Tcl'ers Chat\) that we ought to make [clock seconds] return a wide value at the same time as we implement the rest of these changes, in order to address the Y2038 problem. Alas, the problem goes deeper; the _gettimeofday\(\)_ call \(and Tcl's mirroring of it in the _Tcl\_GetTime_ interface\) is not Y2038-ready. The necessary upgrades to return a 64-bit value for [clock seconds] are outside the scope of this TIP. Several people have informally asked whether 64 bits are enough to hold the microsecond counter. Since 2\*\*64 microseconds is roughly half a million years, the authors are confident that the answer is, "yes." |
Name change from tip/125.tip to tip/125.md.
|
| < | < | | | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 125: Converting between Frame and Toplevel Windows Author: Brian Griffin <[email protected]> Author: Donal K. Fellows <[email protected]> Author: Sacha Schär <[email protected]> State: Final Type: Project Vote: Done Created: 20-Jan-2003 Post-History: Keywords: reparent,Tk Tcl-Version: 8.5 ----- # Abstract This TIP modifies the **wm** command to act as a geometry manager for Frames, allowing them to become Toplevel windows. # Rationale One of the usability features introduced recently in many windowing systems, is the ability to "tear out" or "insert" sub-frames and panes within an application. The most common form of this is the ability to tear off a toolbar, making it an independent window. This feature gives the end user the ability to configure the application in ways that best suit them and improve their overall productivity. Currently there is no mechanism with Tk to move a widget subtree to a new toplevel parent without reconstructing the hierarchy from scratch. The basic command will give the Tk programmer the ability to implement megawidgets that support tear-off toolbars, notebooks, etc., since the children widgets of the frame will follow along, unchanged. An alternative approach has been taken from the orignal **wm toplevel** proposal as described here: In Tk, Toplevel windows are basically a special form of a Frame which are managed by the window manager. The proposal is to add the commands **wm manage** and **wm forget** which will take an arbitrary Frame and allow it to be managed by the window manager, making it a Toplevel window. There are three configure options of Toplevel that are not present on a frame, **-menu**, **-screen**, and **-use**. The options **-screen** and **-use** can only be specified when a Toplevel is created and cannot be modified later. The **-menu** option can be modified after widget creation and should be available on a frame so that when the frame is managed as a Toplevel, the menu can be present, therefore, this option has been added to the Frame widget. When a frame is not managed as a toplevel, the **-menu** option is ignored. Note: because of special conditions of Toplevel, it is necessary to restrict them to only be managed by the window manager; they cannot be converted to frames and therefore, **wm forget** is not allowed on a Toplevel widget. # Reference Implementation TkToolkit patch \#998125 implements the **wm manage** and **wm forget** commands on Unix and Windows. A partial MacOSX implementation is also provided. This implementation only works for buttons and menubuttons. For the remaining Tk widgets to be present in a **wm manage**'d frame, the widgets need to recognize and implement the TK\_URBAN\_RENEWAL flag. The original **wm toplevel** implementation can be obtained [ftp://ftp.model.com/pub/tcl/reframe], with patch files as well as Linux and Win32 builds of 8.3.4 and 8.4.1 available. The _demo.tcl_ file illustrates the basic function. # Known Issues The reference implementation works on Windows and Linux. A Mac implementation has been partially implemented. Because of the Mac architecture, it is necessary to reconstruct widgets in order to remap their window hierarchy. The reference implementation includes a widget flag, TK\_URBAN\_RENEWAL which is used to trigger this reconstruction. Because of assumptions and restrictions, Toplevels can only be managed by the window manager and cannot become frames and be managed by any other geometry manager. This restriction is enforced which means the **-use** and **-screen** options do not present any problem or complication with this proposal. The toplevel **-menu** option has been added to frames. This allows the setting of menus on a frame so that when the frame is managed as a toplevel, the menus will appear, otherwise the option is ignored. # Alternatives An alternative to extending the **wm** command is to make this feature either a method or a configure option of the Toplevel and Frame widget. _A._ [_w_ **detach**] to convert a Frame into a Toplevel, and [_w_ attach**] to convert a Toplevel into a Frame. _B._ [_w_ **configure -toplevel 1**] to convert a Frame into a Toplevel, and [_w_ **configure -toplevel 0**] to convert a Toplevel into a Frame. These different approaches \(wm, method, config\) depend on how the feature is viewed. One view is that the of changing the nature or class \(Toplevel, Frame\) of the widget. An alternative view is that of changing "who" manages the widget \(wm, place, grid, pack\). I suppose another alternative is to follow the precedent of the geometry managers: * **wm** _w_ ?**-transient** _parent_? ?**-overrideredirect** _boolean_? ... * **wm forget** _w_ # Comments _From Sacha Schär <[email protected]>:_ The way the TIP and its alternatives are proposed, a frame can be made into a toplevel and vice versa. However, it is not possible, to move a frame from one toplevel to another. This is of importance even for the most common motivation for this TIP, the possibility to implement a tear-off behaviour. If a frame is going to be teared out of a toplevel window, it might be desirable that it becomes part of another toplevel window, together with some extra decoration. I see, that with this more general behaviour, the path name becomes a problem. Therefore I propose the alternative approach, of making the **-container** and **-use** options dynamically configurable as already discussed in the past _From Brian:_ The problem is that we can't reparent widgets without changing their Tk widget pathname. Doing this introduces all kinds of sticky problems. In practice, the decoration is in the form of Menus, Toolbars, and Footers. All of these things can \(must\) be created and managed as part of the dock/undock process. The way to do this is to create these things the first time a window is undocked, then just "hide" them when redocking the window; they still exist, but are just not mapped anywhere, until the next time the window is undocked. The bottom line is that the **wm manage** command does not do _everything_ you need when performing an undock operation; it is only a small piece of the pie, but a very critical one. # Copyright This document has been placed in the public domain. |
Name change from tip/126.tip to tip/126.md.
|
| < | | | | | | | < | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 126: Rich Strings for Representation Persistence Created: 30-Jan-2003 Author: Donal K. Fellows <[email protected]> Type: Project Tcl-Version: 9.0 Vote: Pending State: Draft Post-History: ----- # Abstract This TIP enriches the standard UTF-8 string representation of every _Tcl\_Obj_ to allow for improved persistence of non-string representations. This, combined with rules for substring and substitution handling, allows the lifetime of an object to correspond far more closely with the more-broadly understood concept of "object lifetime". # Rationale At the moment in Tcl, whenever someone wants to create a stateful entity of limited lifespan \(i.e. an object\) and pass it through a Tcl script, they have to do one of two things: 1. Tie the lifespan of the object to the lifespan of the _Tcl\_Obj_ value that represents it, so that when the internal representation of the value is deleted, so to is the object. 2. Create a table \(typically a hash table\) of objects and have the value passed through the Tcl script be a handle that is really an index into this table. Deletion happens precisely when some kind of delete "method" is called on the object. Each of these techniques has problems. With the first, difficulties arise because it is a fundamental assumption of Tcl that it is always possible to recreate the internal-representation part of a value from the string-representation part of the value. While this is a good assumption for lists, numbers, etc. it is not true for anything where the deletion of the internal-rep results in the deletion of the underlying data structure. Thus, there is a tendency for the object to get deleted far too early. \(In practise, the problem occurs in locations like scripts passed to Tk's [bind] command and in some invocations of the [eval] command.\) Nevertheless, this technique can be used subject to some caveats, and this is done in a number of extensions \(e.g. TclBlend/Jacl, where Java objects are passed through Tcl this way.\) However, the second technique has a different set of troubles. Although the process of explicit deletion works around all the faults with over-early deletion as described above, it instead has a strong tendency to not delete objects at all; it is far too easy to have a resource leak that is fairly difficult to track down. Most Tcl extensions that deal with objects \(and all the ones that predate Tcl8.0, like [incr Tcl]\) use this technique. What we really need is a way to allow non-string object representations to persist substantially longer, so making the first of the two techniques outlined above much more robust. In particular, I have identified the string concatenation, string substitution and substring operations as being in need of attention, though obviously the required work will extend further as well \(the script parser is an obvious target.\) This is the focus of this TIP. # Alterations to the Tcl\_Obj So, what is the best way of maintaining these valuable representations within a supposedly pure-string Tcl\_Obj value? Well, since we do not want to alter the internal representation \(after all, it is that which we would really like to preserve\) we will have to add an extra field \(or potentially more\) to the Tcl\_Obj structure itself. This is technically feasible in a backward-compatible way, as allocation of instances of this structure have always been performed by the Tcl library, but there is a significant downside to this in that the structure is far and away the most common structure allocated in the entire Tcl core. Any field added will have a significant impact on the overall memory consumption of any Tcl-enabled binary. What information do we actually need to store for these representations to be preserved in a string while allowing extraction of the underlying values? The simplest possible option is for a list of string-subrange/object-reference pairs to be associated with the object, probably as an array of simple structures pointed to by a new field of the Tcl\_Obj \(with a NULL indicating that no range of the string has an object associated with it.\) The easiest way of representing those string ranges is as pairs of byte-indexes relative to the start of the string, though character-indexes have much to commend them \(especially when working with strings with a UCS-16 internal representation\) as do direct pointers into the string \(easy to compute, but much more problematic when another string is appended.\) The end of the list would be marked in some obvious way, probably by using a NULL in the object-reference part. This mechanism has the advantage that it keeps the increase in size of the Tcl\_Obj itself fairly small \(i.e. an extra 4 bytes for another pointer on 32-bit platforms\) which is an advantage when you consider the fact that it is likely that most strings in an average Tcl program will not have objects contained within them. This will act to minimise the overall memory overhead. # Concatenation, Substitution and Substring Semantics When two strings with these object annotations are concatenated, it is clear that the resulting string should also have the annotations \(and the actual human-readable part will use the string-representation of the objects\), and this is trivially extended to arbitrary concatenations of strings. Similarly for the taking of substrings with the following restrictions: 1. Where the portion of substring taken corresponds exactly to the part of a string associated with an object, the operation shall instead return the object in question \(which shall be assumed to have a compatible string representation.\) 2. Where a substring wholly contains a range associated with some object, then the resulting substring object will also contain the object associated with the "same" characters. 3. Where a substring only partially overlaps a range associated with an object, that object will not be associated with the corresponding characters in the resultant substring \(unless the object is separately part of the substring due to the other rules, of course.\) The object is associated with the string segment as a whole, and not any one part of it. Substitution, whether of variable contents, script execution results or anything else, is semantically a concatenation operation where some strings are \(as it were\) immediate operands and others are derived from reading variables, executing scripts, etc. Thus, if we start variable _a_ containing an object _Ob1_ and variable _b_ containing an object _Ob2_, the following shall be true: set var x${a}y${b}z => xOb1yOb2z # where characters 1-3 are assocaited with Ob1 # and characters 5-7 are associated with Ob2 set c [string range $var 1 3] # precisely equivalent to [set c $a] set d [string range $var 5 7] # precisely equivalent to [set d $b] # Consequences It is an obvious consequence of this that script evaluation should take into account of these object annotations when attached to the scripts themselves, particularly as the process of parsing can really be regarded as being mostly the taking of \(suitable\) substrings. Only slightly less obviously, it is also the responsibility of all code that stores strings \(and especially scripts\) for future use to store them as _Tcl\_Obj_ instances and not as just plain character strings, and to perform any substitutions it needs to perform in a way that preserves these object annotations on the parts that it is not interested in. This in turn will probably require changes on the part of many extensions to actually turn into reality. On the other hand, there are quite a few objects \(numbers and boolean values are probably very good examples here\) for which this representation preservation is probably not a very good option as the objects in question are perfectly preservable. It makes sense to add some kind of signalling mechanism \(e.g. a bit in a newly added _flags_ field\) to allow the type of a _Tcl\_Obj_ instance to declare that it need not be preserved. As a general note, such a flag would only be useful in "leaf" objects; structural objects \(i.e. those that are intended to contain others, like lists\) would be expected to do without this. Strings \(now a structural as opposed to a leaf type\) probably need even more special handling, but that can really be regarded as a type-specific special case. The flags field mentioned a few paragraphs above would probably have other potential uses \(e.g. for marking an object as being impossible to change into any other type\) though these lie outside the scope of this TIP. Because these changes at the C API level are far reaching and fairly subtle in some cases, this TIP explicitly seeks to introduce this behaviour with a major version number change. Although the alteration at the script level should be small - existing code should continue working without alteration - it is a huge philosophical leap as it will no longer be the case that everything in Tcl will be a string, or at least not a string that you \(or anyone else\) can type. Again, that implies introduction at a new major version number. # Notes * The existing API function _Tcl\_InvalidateStringRep_ will gain additional significance with the introduction of this TIP: its invocation may well trigger the deletion of many objects. * It is probably a very good idea indeed for code that creates objects whose lifespan is meant to persist, to create those objects with string representations composed entirely of alphanumeric characters. An ideal choice might be to use a prefix derived from the type/class of the object, and a suffix that is the address of the object or the next value from some counter variable. # Copyright This document is placed in the public domain. |
Name change from tip/127.tip to tip/127.md.
|
| < | < | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | < > | < < > > | < < > > | | | | | | | | | | | | | | | | | | | | | | | | | | | < > | | < | > | | | > | 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 | # TIP 127: Add an -index Option to [lsearch] Author: Michael Schlenker <[email protected]> State: Final Type: Project Vote: Done Created: 26-Feb-2003 Post-History: Tcl-Version: 8.5 ----- # Abstract Matching the _lsort_ functionality a _-index_ option should be added to the _lsearch_ command to make searching lists in list easier. The _lsort -index_ and the _lsearch -index_ options should accept list style indices like _lindex_ and _lset_ do. This TIP proposes such added options. # Specification Under this proposal the syntax of the _lsearch_ is to be modified to accept two extra options. The _-index_ option: The _lsort_ -index option would get enhanced with multiple index support. lsearch ?-index index? The _-index_ option should work similar to the _-index_ option in the _lsort_ command. If this option is specified, each of the elements of list must itself be a proper Tcl sublist. Instead of searching based on whole sublists, _lsearch_ will extract the index'th element from each sublist and search based on the given element. The keyword end is allowed for the index to search on the last sublist element, and end-index searches on a sublist element offset from the end. For example, lsearch -integer -index 1 {{First 24} {Second 18} {Third 30}} 18 returns _1_, and lsearch -index end-1 {{a 1 e i} {b 2 3 f g} {c 4 5 6 d h}} d returns _2_. The index given to _lsearch -index_ and _lsort -index_ may be either a single scalar index as in the current _lsort_ implementation or the argument to _-index_ may be a list of scalar indices \(similar, but not exactly like the lset/lindex multiple indices\). The -index option causes lsearch and lsort to extract the item for searching or sorting comparision from the list element by using in effect _lindex $element $index_. For example: set record { { {James Dean} {Musician} {some other data} } { {Elvis Presley} {Musician} {some more data} } } lsearch -index {0 0} $record "Elvis" returns _1_. lsort -dictionary -decreasing -index {0 1} $record returns _\{\{\{Elvis Presley\} \{Musician\} \{some more data\}\} \{\{James Dean\} \{Musician\} \{some other data\}\}\}_. Note: The following example is invalid, -index only takes a list as argument, unlike lset and lindex, that take either a list or multiple arguments, that get concatenated by the command. lsearch -index 1 1 $record Presley The _-subindices_ option: The _-subindices_ option should be added only to the _lsearch_ command as a convenience shortcut. It is only a valid option if the _-index_ option is also used. If _-subindices_ is given, _lsearch_ should return a list of indices that can be used directly by _lindex_ or _lset_ to manipulate the element used for searching, instead of the top level element of the list. If _-subindices_ and _-inline_ are specified at the same time, the command returns the value instead of the index. example: lsearch -subindices -index {0 0} $record Elvis returns _\{1 0 0\}_. If no -all option is specified, this is the same as doing: concat [lsearch -index {0 0} $record Elvis] [list 0 0] # Rationale Lists containing one or more level of sublists are a common technique to simulated complex data structures like matrices or records, or for results from database queries. The _lsort_ command was enhanced with the _-index_ option for this case, to handle sorting on sublist keys. The _lsearch_ command does not have this functionality yet, one has to use _foreach_ and _lindex_ to loop over the list one by one. Multiple indices for the _-index_ option to both _lsearch_ and _lsort_ should be added, to make the option more similar to _lset_ and _lindex_ style indices. The _-subindices_ option is a convenience option to make constructs like this example work well: foreach item [lsearch -all -subindices -index {0 0} $record bla] { lset record $item bar } Without the subindices option it could be written as: foreach item [lsearch -all -index $idx $record bla] { lset record [concat $idx $item] bar } # Reference Implementation A reference implementation exists, see the files attached to the Tcl Patch 693836 on SourceForge. <http://sf.net/tracker/?func=detail&atid=310894&aid=693836&group\_id=10894> The reference implementation isn't honouring the -inline option if given in conjuction with -subindices, at the moment. # Copyright This document has been placed in the public domain. |
Name change from tip/128.tip to tip/128.md.
|
| < | < | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | < > | | | < > | | | | | | | | < < < < < < < < < < < < < < < < < < < < < | > > > > > > > > > > > > > > > > > > > > > | | | | | > | 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 | # TIP 128: Ability to Install a Custom Memory Allocator Author: Christophe Cap <[email protected]> Author: Mike Jackson <[email protected]> State: Rejected Type: Project Vote: Done Created: 13-Mar-2003 Post-History: Tcl-Version: 8.6 ----- # Abstract This TIP alters Tcl to allow embedded uses of the Tcl library \(and any extensions\) to either use the Tcl memory allocators as their main allocator \(especially in C\+\+\) or to set the memory allocator that Tcl uses for itself through _ckalloc\(\)_. # Background A while ago I was experiencing troubles when allocating images \([image create photo]\) while memory was already exhausted, my app crashed \(due to known bug item \#698571, which is in the HEAD by now!\) This shouldn't happen anyway since my application had it's new handler set. Tracing down the source of the allocators I noticed that Tcl uses _HeapAlloc\(\)_ \(on Win32\) to allocate its memory. Why not use _malloc\(\)_? # New/Malloc Handler It would be nice to be able to catch memory allocation errors with a custom new handler. A solution could be to replace _HeapAlloc\(\)_ \(on Win32\) and other platform specific memory handlers should be replaced by _malloc\(\)_. This way a new handler can by set through _set\_new\_handler\(\)_. Note that the Microsoft VC\+\+ compiler has some ANSI incompatibility in that it uses _\_set\_new\_handler\(\)_ rather than _set\_new\_handler\(\)_. We would naturally conceal this platform difference. For example: #include <new> // // New handler for Microsoft Visual C++ compiler // #ifdef _MSC_VER #include <new.h> int __cdecl _newHandler(size_t size ) { // Do whatever return 0; } #else // // Ansi C/C++ new handler // void __cdecl _newHandler( void ) { // Do whatever } #endif void sethandlers(void) { // Microsoft compiler #ifdef _MSC_VER _set_new_handler (_newHandler); // Setup new handler _set_new_mode( 1 ); // Re-route malloc failures to new handler ! // Ansi compiler #else set_new_handler (_newHandler); // ANSI new handler #endif } # Tcl Implementation The above suggested solution could work for some compilers, but may not for all \(some compilers might not support setting a malloc failure callback.\) Therefore a Tcl custom new handler functionality could be implemented that handles Tcl specific memory allocation failures. Something like: _Tcl\_SetMemHandler\(\)_? # Copyright This document has been placed in the public domain. |
Name change from tip/129.tip to tip/129.md.
|
| < | < | | | | | | | | | > | | | | | | | | | | | | | | | | > | 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 | # TIP 129: New Format Codes for the [binary] Command Author: Arjen Markus <[email protected]> Author: Torsten Reincke <[email protected]> State: Final Type: Project Vote: Done Created: 14-Mar-2003 Post-History: Keywords: IEEE,binary data,Tcl Tcl-Version: 8.5 ----- # Abstract This TIP proposes to add a set of new format codes to the **binary** command to enhance its ability to deal with especially non-native floating-point data. The assumption is that current limitations are due to the distinction between little-endian and big-endian storage of such data. # Introduction The current **binary** command can manipulate little-endian and big-endian _integer_ data, but only _native_ floating-point data. This means that binary data from other computer systems that use a different representation of floating-point data can not be directly handled. The lack of format codes to handle "native" integer data means that one has to distinguish the current platform's byte ordering to be platform-independent, whenever the **binary** command is used. Most current computer systems use either little-endian or big-endian byte order and the so-called IEEE representation for the exponent and mantissa. So, the main variation to deal with is the endian-ness. Some popular file formats, like ESRI's ArcView shape files, use both types of byte order. It is difficult \(though not impossible\) to handle these files with the current set of format codes. It should be noted that there _is_ more variety among floating-point representation than just the byte order. This TIP will not solve this more general problem. # Proposed Format Codes Format codes should be available to catch the two main varieties of byte ordering. There should, both for reasons of symmetry and for practical purposes, also be a full set to deal with "native" data. For integer types there are no codes to deal with native ordering. So: * **t** \(tiny\) for short integers, using native ordering. * **n** \(normal\) for ordinary integers, using native ordering. * **m** \(mirror of "w"\) for wide integers, using native ordering. The floating-point types will be handled via: * **r**/**R** \(real\) for single-precision reals. * **q**/**Q** \(mirror of "d"\) for double-precision reals. where the lower-case is associated with little-endian order and the upper-case with big-endian order. # Implementation Notes The implementation for the integer types is simple: * The new format codes are synonyms for the current ones, but different ones for each endian-ness. The implementation for the floating-point types is somewhat more complicated, this involves adding byte swapping, if the ordering of the platform does not correspond to that of the format code. # Copyright This document is placed in the public domain. |
Name change from tip/13.tip to tip/13.md.
|
| < | < | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 13: Web Service for Drafting and Archiving TIPs Author: Don Porter <[email protected]> Author: Donal K. Fellows <[email protected]> State: Accepted Type: Process Vote: Done Created: 21-Nov-2000 Post-History: ----- # Abstract This document proposes the TCT provide a service on the World Wide Web for drafting and archiving TIPs and for providing TIPs in a variety of formats. A reference implementation is provided, and its server requirements are outlined. # Background It has been proposed \(see [[2]](2.md)\) that the TCT manage its projects and procedures through a set of public documents known as Tcl Improvement Proposals, or TIPs. A format for TIPs has been approved \(see [[3]](3.md)\), and although final approval of [[2]](2.md) is still pending, several TIPs have been submitted, discussed, and revised, and a few have been approved, so acceptance of TIPs in some form seems likely. A prototype system has been provided by Donal Fellows <[email protected]> <http://www.cs.man.ac.uk/fellowsd-bin/TIP/> that delivers TIPs to visitors in a variety of formats. However, that system lacks archiving of each revision of each TIP, and offers no interface \(through the web or otherwise\) for making revisions to TIPs. The TIP format was inspired by the format used by the Tcl'ers Wiki <http://www.purl.org/thecliff/tcl/wiki/> . The true power of the Tcl'ers Wiki, though, is not in the particular format it uses, but in the fact that it empowers the whole Tcl community to contribute to a common set of resources. The Tcl'ers Wiki shows that valuable resources can arise out of the unrestricted efforts of volunteers from the community. # Problems with Current TIP Infrastructure. The Fellows web interface to the TIP Document Collection <http://www.cs.man.ac.uk/fellowsd-bin/TIP/> offers valuable browsing access to TIPs in a variety of formats. It accomplishes the important goal of making TIPs public. However, it suffers from two significant shortcomings: * Revisions are only possible through the TIP Editor: > Currently the only way to revise a TIP is to e-mail a new revision to the TIP Editor and wait for it to replace the old revision. As more TIPs are submitted, and as each TIP is more frequently revised, this bottleneck will not be tolerable. > Discussion about TIPs currently takes place in Usenet newsgroups and on mailing lists, but because there is no easy access to revising the TIPs themselves, the new information and viewpoints arising in these discussions are not being folded back into the TIPs. This means the TIPs are failing in their intended role to present a full history of an issue to later readers. It also means newcomers to a TIP cannot receive a full briefing in one place, but must chase down discussions in mailing list and Usenet archives. Few people do that, but instead repeat points already made. The discussions about [[6]](6.md) reflect this problem. * An archive of each revision of each TIP is not maintained: > Although [[2]](2.md) refers to TIPs as being stored in a revision control system, probably a CVS repository, the Fellows TIP collection is not maintained in such a system. Since a TIP is an archive of a public discussion of an issue, it is important to be able to access the history of changes to each TIP. > The ability to retrieve and restore earlier revisions of a TIP will be especially important if public revision is permitted, so that any TIP contents that are incorrectly removed, whether by accident or malice, can be restored. # Proposal An improved system for archiving and revising TIPs is proposed: 1. TIPs will be archived in a CVS repository. 1. Anyone with the power to call a TYANNOTT vote will have commit access to this repository through either :pserver: or ssh access. With this access, they will be able to revise any part \(header or body\) of any TIP \(whether in _State: Draft_ or not\). Everyone having this access will be trusted to modify TIPs only in conformance with the TIP format and the TCT procedures. 1. An enhanced version of the Fellows TIP rendering engine will display an [Edit] link at the bottom of each TIP eligible for web-editing when that TIP is rendered in HTML. 1. For any TIP in state Draft, and for which a vote is still pending, the [Edit] link will lead to an HTML form for submitting a revised TIP. For other TIPs, no [Edit] link will appear, and an attempt to directly access web-editing of such a TIP will lead to a message stating that the TIP may not be edited through the web interface. 1. The HTML editing form will display the TIP header, but will not make it available for editing. The HTML form will require that an e-mail address be entered, and will allow a name to be entered as well. A <TEXTAREA> will be initialized to hold the current TIP abstract. A second <TEXTAREA> will be initialized to hold the current TIP body. Users of the form will revise the abstract and the body, then submit the form. 1. The TIP rendering engine will receive the revisions, and will use CVS client commands to merge the revisions with other revisions and commit the revised TIP to the TIP CVS repository. If a conflict occurs during a merge, the TIP body including the conflicts will be returned to the user in another HTML form to resolve the conflict. > Note that the CVS commit function of the TIP rendering engine implies that the CGI process in which the TIP rendering engine runs must have a user ID with commit access to the TIP CVS repository. 1. In the revised TIP checked in to CVS the submitter of the revision will be added as an Author in the header of that TIP. # Reference Implementation The modifications to the Fellows TIP rendering engine that add the capabilities proposed above are now merged in. The TIP rendering engine is maintained and publically available <http://sourceforge.net/projects/tiprender/> . To enable the web-editing features, set the Tcl variable FEATURE\(EDIT\) to 1 in the file config.tcl. A working version of the proposed web service is available at <http://purl.org/tcl/tip/> For what it's worth, this TIP was created primarily within a web browser, making revisions through the web interface provided by the reference implementation. One remaining shortcoming of the reference implementation is that it provides no mechanism for uploading images to the TIP repository. Images still need to be submitted through the TIP Editor, or someone else with commit access to the TIP CVS repository. # Server Requirements The reference implementation imposes the following requirements on a server: 1. The server provides an HTTP server that serves the public Internet, and supports the CGI interface. 1. CVS client software must be installed on the server. 1. The CVS repository containing TIPs must be on the server itself. This is due to a CVS limitation that _loginfo_ scripts run on the machine housing the CVS repository, and the reference implementation uses a _loginfo_ script to keep the TIPs presented through the web up to date with the commits to the repository. 1. The CVS repository must offer commit access over the Internet using either :pserver: or ssh to everyone with authority to call a TYANNOTT vote. 1. The user under which the HTTP server runs its CGI processes must have commit access to the TIP CVS repository. This may have security implications. # Future Improvements Once the TIPs are housed in a CVS repository, other services should be easier to implement. Another browsing interface could be provided using cvsweb <http://stud.fh-heilbronn.de/~zeller/cgi/cvsweb.cgi/> to allow anyone in the community to browse TIP history. Another _loginfo_ script could provide e-mail notices when a TIP is revised to users who registered their interest in that TIP. # Acknowledgments Thanks to Donal Fellows for the original TIP rendering engine and his assistance merging in the changes. Thanks to Brent Welch for providing the server and his assistance getting it configured for use. Thanks to Mark Harrison for his assistance with managing browser caching issues. ---- # Comments from the TCT > It might be a good idea to make the Abstract into a seperate <textarea> and treat that specially; I've been applying the rule that a TIP's abstract should be a single paragraph \(it is implicit in the way I generate XML for instance\) and that would be much easier to enforce through this route. It would also have the advantage of discouraging people from placing their whole rationale in the abstract - which I've seen in several first drafts by people who shall remain nameless - and prompting the creation of TIPs more in keeping with the general concept of publishable documents. > It would also be nice if each page had a way of viewing the TIP's revision history \(by a link to a suitably setup CVSweb URL?\) The way that SourceForge does its CVS-over-the-web is very nice indeed... > _Donal K. Fellows <[email protected]>_ # Author replies to comments Some comments I see above, or received in e-mail: * _Add a link to [[3]](3.md) on the edit page. Display [[3]](3.md) in a new window._ > Link added. I don't believe in deciding to open new browser windows for the user. If the user wants to open the link in a new window, she knows how to do that. * _Add an interface to create a new TIP_ > For now, I'm trying to stick with the TIP procedures proposed in [[2]](2.md), where only the TIP Editor gets to create a new TIP, so all TIPs should still be originally submitted to him. If the TCT rejects this proposal and adopts a different policy, we can revisit this question. * _Browser caching makes it look like the edits were not made_ > Based on advice from Mark Harrison and others, I've added HTTP headers that should prevent caching. Please try it again. * _I had the server time out on me_ > That's troubling. Can anyone seeing this problem provide any more information. What were the circumstances, in detail? * _Add links to an interface showing revision history_ > Check out the [History] links at the bottom of the HTML rendered pages. Thanks to Donal Fellows for coding that up. \(OK, so we \*did\* reinvent CVSWeb.\) * _A separate <TEXTAREA> for the Abstract_ > This is now implemented. Please give it a try. # Copyright This document has been placed in the public domain. |
Name change from tip/130.tip to tip/130.md.
|
| < | < | | | | | | | > | | | | | | | | | | | | | | | | | > | 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 | # TIP 130: Unique DDE server names. Author: Pat Thoyts <[email protected]> State: Final Tcl-Version: 8.5 Created: 23-Mar-2003 Type: Project Vote: Done Post-History: ----- # Abstract The _dde_ package server registration code should ensure that the server names are unique. The proposed changes will mean end-user visible changes for some scripts. # Rationale This TIP is really driven by Bug 219293 <http://sf.net/tracker/?func=detail&aid=219293&group_id=10894&atid=110894> The DDE system actually identifies servers by combination of window ID and a service and topic string identifier. There is nothing to prevent multiple servers having the same string identifiers but it is then a problem to determine which server you need to communicate with. The _tk appname_ command handles a similar situation by making the name unique during registration by appending a numerical suffix to the suggested name and then returning the name registered as the result of the command. # Proposed Changes This TIP proposes to use the _tk appname_ unique name algorithm within the DDE server-name registration code. This TIP also proposes a _-force_ option to this command to force the suggested name to be registered. The _-force_ option would then provide the current registration scheme. # Reference Implementation See the patch attached to SF patch 690354 <https://sourceforge.net/tracker/?func=detail&aid=690354&group_id=10894&atid=310894> # Consequences Firstly the _dde servername_ command may register a different name than that provided to the command. Scripts will need to check the name actually registered by either maintaining the result of this command, or by executing the _dde servername_ command without any arguments. This may impact scripts that assume the supplied argument was in fact the name registered. Secondly, the name registration code must obtain a list of the dde server names currently registered on the system. It can do this by effectively calling _dde services TclEval_. In previous versions of the _dde_ package there is a potential for the _dde services_ command to hang in the presence of applications that are not processing messages. However, this issue has been addressed by Bug 707822's resolution. # Copyright This document is hereby placed in the public domain. |
Name change from tip/131.tip to tip/131.md.
|
| < | < | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | < > | | | | | | < > | | | | < > | | | < | > | < > | | | < > | | < > | | < > | | | > | 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 | # TIP 131: Read My Mind and Do What I Mean Author: Joe English <[email protected]> State: Draft Type: Project Vote: No voting Tcl-Version: 8.5 Created: 01-Apr-2003 Post-History: ----- # Abstract A new Tcl command is proposed, _rmmadwim_. This is an acronym for \`\`Read My Mind and Do What I Mean_. This command has obvious utility. # Specification The _rmmadwim_ command shall take no arguments. When invoked, the Tcl interpreter shall read the programmer's mind and do what he or she intends. _NOTE:_ It is very important that _rmmadwim_ read the _programmer's_ mind, not the end user's. Otherwise the consequences could be disastrous, since end users rarely have a firm grasp of what the original programmer was up to. As a consequence of this command, there is also a corresponding function for _expr_ which applies the same principles to general mathematical computation: set result [expr {rmmadwim()}] This extra functionality is easy to enable: rmmadwim # Rationale What Tcl needs in order to succeed in the marketplace is a feature that no other programming language provides, a "killer app" as it were. The Tk toolkit, Expect, cross-platform portability, scripted documents, tkcon, and the [incr Tcl] "toaster" example are all well and good, but they have clearly failed to push Tcl usage to the point of having critical mass. The _rmmadwim_ command would provide a powerful enough incentive that even Perl programmers would be compelled to switch languages. # Reference Implementation A skeletal implementation is included below. Clearly some of the details remain to be flushed out, but this is a simple matter of programming \(SMOP\). It should be a fun weekend project for Richard Suchenwirth. File: _tcl/generic/tclCmdMZ.c_ Function: _Tcl\_RmmAndDWIMObjCmd_ /*ARGSUSED*/ int Tcl_RmmAndDWIMObjCmd(dummy, interp, objc, objv) ClientData dummy; /* Not used. */ Tcl_Interp *interp; /* Current interpreter. */ int objc; /* Number of arguments. */ Tcl_Obj *CONST objv[]; /* Argument objects. */ { int status; Tcl_Obj *intentions; if (objc != 1) { Tcl_WrongNumArgs(interp, 1, objv, NULL); return TCL_ERROR; } status = TclReadProgrammersMind(interp, &intentions); if (status != TCL_OK) { return status; } status = TclDoWhatIsMeant(interp, intentions); return status; } # Security Implications It was pointed out that the ability to read the programmers' mind carries with it certain security and privacy implementations. To address this, the following code should be executed whenever a safe interpreter is created: # # Query the programmer's mind to obtain his or her # P3P settings (See "Platform for Privacy Preferences", # <URL: http://www.w3.org/P3P >) # rmmadwim # # Disable any internal commands that are in conflict # with those settings: # rmmadwim In addition, the Tcl release notes should give a clear indication to programmers about the new security implications for non-Safe interpreters. # Copyright This TIP is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License; either version 2 of the License, or \(at Richard Stallman's discretion\), any later version. Just kidding. Public domain, as usual. |
Name change from tip/132.tip to tip/132.md.
|
| < | < | | | | | | | | | > | | | | | | | | | | | < > | < | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 132: Revised Floating-Point Conversions in Tcl Author: Kevin Kenny <[email protected]> Author: Donal K. Fellows <[email protected]> State: Final Type: Project Vote: Done Created: 31-Mar-2003 Post-History: Keywords: floating point,IEEE,precision Tcl-Version: 8.5 ----- # Abstract This TIP proposes several changes to the conversion between floating point numbers and character strings. The changes are made to restore the "everything is a string" contract that Tcl implicitly makes; without them, there are observable differences in the behavior of floating point numbers, depending on the state of the internal representation. # Rationale In today's \(8.4\) Tcl, there are several gaffes that make floating-point arithmetic less useful than it might be, and cause confusion for the users. Chief among these is that string equality does _not_ imply value equality for floating point numbers: % set tcl_precision 12 12 % set a [expr 1.00000000000123] 1.0 % set b [expr 1.0] 1.0 % expr { $a == $b } 0 % expr { $a eq $b } 1 This behavior flies in the face of Tcl's "everything is a string" mantra. In the interaction above, it is visible that _a_ and _b_ are _not_ entirely strings; they have identical string representations, but still test to be unequal with "==". The underlying cause of the behavior is the fact that the default setting for _tcl\_precision_ loses precision when converting the floating-point number to a string. Behaviors like this have caused Tcl's _cognoscenti_ to recommend that all programs set _tcl\_precision_ to 17; once this setting is made, double-to-string conversions are invertible, and everything is once again a string. \(Why 17? With IEEE-754 arithmetic, 17 decimal digits suffice to distinguish between any two floating point numbers, no matter how small their difference. No smaller number of digits suffices.\) Why is _tcl\_precision_ not 17 by default? The reason appears to be that when the precision is set that high, the default IEEE-754 semantics for floating point conversions cause a certain degree of trouble. They require that the decimal representation be the nearest decimal representation to the value of the floating-point number that has the given number of significant digits. This conversion gives rise to peculiarities: % set tcl_precision 17; expr 0.2 0.20000000000000001 The peculiar behavior is, for the most part, suppressed by a lower value for _tcl\_precision_: % set tcl_precision 16; expr 0.2 0.2 The lower value, nevertheless, introduces the trouble above. This TIP proposes a solution to both problems. # Specification This TIP proposes the following changes to the floating point conversions in the Tcl library: 1. The default value of _::tcl\_precision_ shall be changed to 0. A value of 0 \(currently an error\) shall be interpreted to mean that a number shall be formatted using the smallest number of decimal digits required to distinguish it from the next floating point number above it and the next floating point number below. Other values of _tcl\_precision_ shall continue to work as they do in Tcl 8.4. The documentation shall formally deprecate changing _::tcl\_precision_ to any other value, warning that doing so risks both loss of precision and inconsistency between string equality and "==". 1. The default input conversion of floating-point numbers, _SetDoubleFromAny_ shall be documented to guarantee precise rounding \(generally to within one-half a unit of the least significant place [1/2 ULP]\). IEEE-754 rounding semantics are correct for this input. The _strtod_ procedure from the standard C library shall _not_ be used for this conversion, since so many implementations are buggy; instead, a Tcl implementation shall be developed from scratch based on the algorithms developed by Burger and Dybvig <http://citeseer.ist.psu.edu/28233.html> . \(It is worthy of note that several platforms already eschew the native _strtod_ in favour of one provided in the _compat/_ library, because of known bugs.\) 1. When _tcl\_precision_ is zero, the output conversion of floating-point numbers, _UpdateStringOfDouble,_ shall convert a floating-point number to the unique string that satisfies the following constraints: > \* if reconverted to a binary floating point number, it yields a number that is the closest among all strings having the given number of significant digits. > \* if there is more than one string that is equally close but neither string yields the given number exactly, then the string with the even digit in the least significant place is chosen. > \* if there is more than one string with at most the given number of significant digits that yields the given floating-point number, but one has fewer significant digits than the other, then the shorter one is chosen. For example, % expr 1e23 > > returns _1e\+23_, not _9.9999999999999992e\+22_, even though the latter is a nearer representation of the exact floating-point value. > \* if there is more than one string with at most the given number of significant digits that reconverts exactly to the same floating point number, and all such strings are equally long, then the one closest to the given floating point number is chosen. > \* if a floating point number lies exactly at the midpoint of two strings with the same number of significant digits, the one with an even digit in the least significant place is chosen. 1. The test suite for Tcl shall be upgraded to include suitable test vectors for assessing correct rounding behavior. The paper by Verdonk, Cuyt and Verschaeren in the References, and the associated software, present a suitable data set for inclusion. 1. The input and output conversions shall allow for the IEEE special values \+Inf, -Inf, and NaN \(and for denormalized numbers\). The [expr] command shall be changed to allow \+Inf and -Inf as the result of an expression; NaN shall still cause an error. Tcl\_GetDoubleFromObj shall treat \+Inf and -Inf as it does any ordinary floating point number, and return an error for NaN. 1. The [binary scan] and [binary format] commands shall explicitly permit infinities and NaN as values. _Donal K. Fellows notes that..._ the **expr** command will handle Inf and NaN quite well if asked nicely; it just won't return them. % expr {1 / Inf} 0.0 # References The basic principles of correctly-rounded floating point conversions have been known for a good many years. Perhaps the two most seminal papers on modern floating point conversion are: > William D. Clinger, _How to Read Floating Point Numbers Accurately_, Proceedings of the ACM Conference on Programming Language Design and Implementation, June 20-22 1990, pp. 92-101. <http://citeseer.nj.nec.com/clinger90how.html> > Guy L. Steele Jr. and Jon L. White, _How to print floating-point numbers accurately_. In Proceedings of the ACM Conference on Programming Language Design and Implementation, June 20-22 1990, pp. 112-126. <http://doi.acm.org/10.1145/93542.93559> Both of these papers inspired David Gay to implement a library to do correct rounding in floating point input and output conversions: > David M. Gay, _Correctly rounded binary-decimal and decimal-binary conversions_, Numerical Analysis Manuscript 90-10, AT&T Bell Laboratories, Murray Hill, New Jersey, November 1990. <http://citeseer.nj.nec.com/gay90correctly.html> The algorithms for output conversion that appear in the reference implmentation are a hybrid of Gay's and the ones presented in: > Robert G. Burger and R. Kent Dybvig, _Printing Floating-Point Numbers Quickly and Accurately_, SIGPLAN Conf. on Programming Language Design and Implementation, 1996, pp. 108-116. <http://citeseer.ist.psu.edu/28233.html> A reasonably comprehensive set of test vectors detailing problem cases for rounding conversions is documented in: > Brigitte Verdonk, Annie Cuyt, Dennis Verschaeren, _A precision and range independent tool for testing floating-point arithmetic II: Conversions_, ACM Transactions on Mathematical Software 27:2 \(March 2001\), pp. 119-140. <http://citeseer.nj.nec.com/verdonk99precision.html> # Reference Implementation A partial reference implementation of this TIP is available in CVS on the _kennykb-tcl-numerics_ branch. Since it requires additional third-party code that is not yet in the core, a different module name is required to check it out: export CVSROOT=:ext:[email protected]:/cvsroot/tcl cvs -q checkout -rkennykb-tip-132 tcl_numerics The implementation is essentially complete; it includes changes to the documentation and test suite needed for this TIP. # Acknowledgments The discussion of just why 17 is magical was prompted by a suggestion from Lars Hellstroem. # Copyright Copyright \(c\) 2005 by Kevin B. Kenny. All rights reserved. This document may be distributed subject to the terms and conditions set forth in the Open Publication License, version 1.0 <http://www.opencontent.org/openpub/> . |
Name change from tip/133.tip to tip/133.md.
|
| < | < | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 133: Extending [expr] Operators Author: Richard Suchenwirth <[email protected]> State: Draft Type: Project Vote: Pending Created: 08-Apr-2003 Post-History: Tcl-Version: 8.7 ----- # Abstract This TIP proposes a way to define new operators for conditions and the **expr** command. It also includes demonstrations of how it might work in the examples: **in** tests inclusion in a list, and **and**, **or**, and **not** are aliases for "**&&**", "**\|\|**", "**!**". # Rationale Inclusion of a value in a list is frequently tested with the construct if {[lsearch -exact $list $value] >= 0} {...} The proposal, first brought by Reinhard Max in the Tcl Chatroom, is to allow an _in_ operator in the language understood by **expr**, and the condition parts of **for**, **if** and **while**, so that the above can be written as if {$value in $list} {...} This is shorter to type and much better to read. In the same vein, I propose to allow operators "**and**", "**or**", "**not**" to be resolved exactly like the current "**&&**", "**\|\|**" resp "**!**" The new "operator aliases" are not shorter than the original operators, but definitely better readable - and easier typed too, as no Shift \(or Alt-Gr on German keyboards\) key is needed. When Tcl was young, almost all users knew C, so the C style operators were a good choice. In recent years, there is tendency that Tcl is used by persons who have no or less experience with C, but come from other languages \(etc. BASIC variants have the AND, OR, NOT operators\) or have Tcl as a first language. For all these, the option of natural-language operators will make the learning just a little bit easier. # Implementation Proposals Donal K. Fellows remarked \(on an earlier proposal relating to just an **in** operator\) in the Tcl Chatroom: "On the plus side, it shouldn't be hard to implement \(might need an extra opcode for **lsearch**, but that's pretty straightforward.\)" Pascal Scheffers proposed an extension mechanism for **expr** and conditions, so the proposed extensions to the expression language can be done in Tcl, with the commands: expr_register_operator in {val list} {expr {[lsearch -exact $list $val]>=0}} expr_register_operator and {p q} {expr {$p && $q}} expr_register_operator or {p q} {expr {$p || $q}} expr_register_operator not {p} {expr {!$p}} Such operator registrations can have one or two arguments \(for unary and binary operators, respective\) in the second argument. The third argument is a body that is evaluated, with local variables from the argument list substituted, and returns the resulting value, to be substituted for the operator and its operands. Alternatively, one could stipulate that **expr** interprets its arguments in the above sense when called like this: expr operator in {val list} {expr {[lsearch -exact $list $val]>=0}} expr operator and {p q} {expr {$p && $q}} This would currently raise an error, hence cannot break existing code. For a simple start, it shall be an error to define an operator both as unary and binary. Rules for operator precedence, and a way of specifying the precedence level, will still be needed. A feature sometimes discussed in news:comp.lang.tcl, an assignment operator, could in the same way easily be added by users who so want: expr operator = {varName value} {upvar 1 $varName var; set var $value} Reinhard Max has also proposed a unary **empty** operator: expr operator empty {list} {expr {[llength $list]==0}} # Copyright This document has been placed in the public domain. |
Name change from tip/134.tip to tip/134.md.
|
| < | < | | | | | | | > | | | | | | | > | 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 | # TIP 134: Subsystem Per-Thread Data Interfaces Author: Colin McCormack <[email protected]> State: Withdrawn Type: Project Vote: Pending Created: 12-May-2003 Post-History: Tcl-Version: 8.5 ----- # Abstract Tcl core subsystems per-thread data is good, because it modularises the core. None of the structures or access keys are exported, which is bad, because it makes modification to these subsystems difficult in a CVS world. # Rationale If one wishes to track the CVS while writing modifications to core subsystems one needs to minimally impact the existing source files while adding or changing subsystem functionality. Since most subsystem global state is kept in Thread Specific Data, and access to this state is necessary for subsystem modifications, providing an interface would ease coding at the core subsystem level. Modular encapsulation would be preserved by conditionally compiling API elements useful only to subsystem development and not intended for extension development. # Justification The degree of modularity of the core would remain unchanged, access to subsystem TSD would presumably only be used for subsystem development, but would enable that development to proceed more easily - one could extend subsystems as easily as one currently writes extensions. I think the degree of potential abuse is likely to be low. # Outline of Proposal Each Thread Specific Data structure should be named uniquely for each subsystem. Each subsystem should have its own .h header file Each subsystem should export a function like _tclTSD<subsystem>_ returning pointer to its TSD. This API should be conditionally compiled, so that it's clear that it's not available to normal extensions. # Implementation The implementation of this TIP is trivial. # Copyright This document has been placed in the public domain. |
Name change from tip/135.tip to tip/135.md.
|
| < | | | | | < | | | | > | | | | | | | > | 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 | # TIP 135: Change 'dde servername -exact' Option to -force Author: Pat Thoyts <[email protected]> Type: Project State: Final Vote: Done Tcl-Version: 8.5 Keywords: dde Created: 17-May-2003 Post-History: ----- # Abstract [[130]](130.md) provides for unique DDE server name registration. This TIP renames one of the options it defines to better reflect its behaviour. # Rationale The dde extension, as modified by [[130]](130.md), includes an option _-exact_ to force the name to be that specified. This TIP proposes to change this options name to _-force_ which better reflects its purpose. As [[130]](130.md) has only just been implemented, now is the time to make this change before it is is included in any public release of Tcl. # Copyright This document is placed in the public domain. |
Name change from tip/136.tip to tip/136.md.
|
| < | < | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 136: Large List Initialisation Author: Simon Geard <[email protected]> State: Final Type: Project Vote: Done Created: 25-May-2003 Post-History: Tcl-Version: 8.5 ----- # Abstract This TIP proposes the addition of a list initialisation command so that large lists can be easily and efficiently initialised. # Rationale With the advent of the _lset_ command in Tcl 8.4 it seems to me that we need a method of efficiently initialising large lists that can then be used as areas of preallocated memory. From a users point of view it can be much easier to preallocate say a 1000 element array and then use _lset_ and _lindex_ to manipulate it than using _lappend_ to build it up. Having posted the idea to the tcl-core mailing list various alternatives were suggested to create a list of 1000 x characters: 1. _lappend_ in a loop unset -nocomplain s for {set i 0} {$i < 1000} {incr i} {lappend s {x}} 2. _split_ting of a string set s [split [string repeat x 1000] ""] 3. Direct construction of the string form set s x[string repeat " x" 999] None of these is particularly satisfactory. \(1\) seems inefficient since there are 1000 lappend operations, \(2\) is not general enough since it doesn't generalise to more than one character and \(3\) doesn't actually create a list. \(2\) and \(3\) also suffer from the problem that they are not at all obvious to new users and do nothing to dispel the notion that "everything is a string" in Tcl. # Implementation I propose the introduction of a new command, _lrepeat_: lrepeat <number> <element1> ?<element2>? ?<element3>? ... which returns a list of length <number> \* \(number of elements\). The new list is the given element sequence repeated <number> times. <number> must be a positive integer and each <element.> a list or string. Examples: lrepeat 100 0 - returns a list of 100 zeros lrepeat 100 [lrepeat 100 0] - returns a 100x100 matrix (list of lists) of zeros lrepeat 3 a b c - returns a nine-element list {a b c a b c a b c} lrepeat 1 a b c - identical to [list a b c] # Reference Implementation I have implemented this command. A patch against the Tcl 8.4.3 source, which implements the command and provides both tests and documentation, is available from <http://homepage.ntlworld.com/whiteowl/tcl/tcl843-lrepeat.patch> The directory also contains timing information and code which demonstrates a performance gain of over ten times for large lists. # Copyright This document has been placed in the public domain. |
Name change from tip/137.tip to tip/137.md.
|
| < | < | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 137: Specifying Script Encodings for [source] and tclsh Author: Anton Kovalenko <[email protected]> State: Final Type: Project Vote: Done Created: 29-May-2003 Post-History: Tcl-Version: 8.5 ----- # Abstract This TIP proposes a way to specify encoding used to read a script with _source_ command and \(tclsh, wish\) shell. # Rationale Now all Tcl scripts are expected to be in the system encoding. An author of a script or a package can't specify concrete encoding to source the script or the files of package. Common practise is to assume that encoding to be superset of ASCII, and not to use non-ASCII characters in the scripts that are targeting the wide audience of potential users. There's a way to specify UNICODE literals with \\uXXXX sequences. But it's not an universal and convenient way - this sequences aren't substituted in \{\}-quoted strings, and they can't be edited in WYSIWYG editors without special \(and hence uncommon\) support. This TIP proposes to add the _-encoding_ option support to _source_ command and to tclsh and wish. Thus, package authors will be able to specify encoding of the package files in _pkgIndex.tcl_; and script authors will be able to specify the script encoding when calling tclsh \(either in the first line beginning with _\#!_ or in the line where the _exec tclsh "$0" "$@"_ is located\). This TIP also proposes to use utf-8 for all the standard system scripts, for _pkgIndex.tcl_ and _tclIndex_ files. Now they all are supposed to be in the system encoding \(message catalogs do not need this support, as they are already always loaded using the UTF-8 encoding scheme\), and it could event prevent Tcl itself from running when system encoding is not a compatible superset of ASCII. # Specification Tclsh will allow the encoding to be specified on the command-line in two forms: the first form is _-encoding name_ as two separate arguments, and the second is _-e:name_ \(a single argument.\) The second form is intended for when the script begins with _\#!_ and is because Unix kernels pass extra parameters from the _\#!_ line as a single argument. This very short notation \(-e:\) is chosen because some Unices limit the _\#!_ line to the length of 32. To implement all these options, this TIP proposes a new C-level public API function Tcl\_FSEvalFileEx, which is similar to Tcl\_FSEvalFile, but takes one extra argument that must be an encoding name or NULL \(to use system encoding\). int Tcl_FSEvalFileEx(Tcl_Interp *interp, Tcl_Obj *pathPtr, CONST char *encodingName); Common use of this new options will be like this: 1. In a script: !#/usr/bin/tclsh -e:utf-8 do something... > or it could be: #!/bin/sh # I wish to use tclsh \ exec tclsh -encoding utf-8 "$0" "$@" 2. In a _pkgIndex.tcl_: package ifneeded pkg 1.02 [list source -encoding utf-8 \ [file join $dir pkg.tcl]] # Implementation The partial implementation of this TIP can be found at <http://sourceforge.net/projects/tcl> as Patch \#742683. Some fixes to source system scripts and pkgIndex'es in utf-8 are not yet there. But with the existing implementation of "-encoding", it would be really easy to implement. # Copyright This document is placed in the public domain. |
Name change from tip/138.tip to tip/138.md.
|
| < | < | | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 138: New TCL_HASH_KEY_SYSTEM_HASH option for Tcl hash tables Author: Kevin Kenny <[email protected]> Author: Joe Mistachkin <[email protected]> State: Final Type: Project Vote: Done Created: 29-May-2003 Post-History: Keywords: thread specific data, hash table, memory allocation Tcl-Version: 8.5 ----- # Abstract This TIP proposes a new flag in the Tcl hash table API in support of a proposed rework of thread-specific data management. # Introduction The Tcl hash table constructor, _Tcl\_InitCustomHashTable_, provides a reasonably flexible means of creating a hash table that is managed by the application. It allows for custom procedures to calculate hash values for keys, to compare keys for equality, and to allocate and free hash table entries. It always, however, allocates the hash table itself by means of _ckalloc_ and _ckfree_. This use of Tcl's main allocator is normally not a problem, but a recent application of custom hash tables has exposed the need, from time to time, of using the system allocator \(_TclpSysAlloc_ and _TclpSysFree_\) directly. The motivating problem is that thread-specific data on certain versions of Windows is limited to only a small number of blocks per process \(64 on at least one version\). The proposed fix, which Joe Mistachkin is pursuing, involves replacing the system calls for managing thread-local storage with calls that manage the thread-specific data blocks in a per-thread hash table. Reviewing and testing the change revealed an unfortunate circular dependency. A call to _Tcl\_InitCustomHashTable_ would attempt to allocate the array of hash buckets by a call to _ckalloc_ - which translates to _TclpAlloc_. On a threaded build, the first thing done in this routine is to retrieve the allocation cache via _TclpGetAllocCache._ This in turn, once we avoid the use of _TlsAlloc_, winds up trying to create a thread-specific data block to hold the allocation cache. The new thread-specific data manager in turn must allocate a hash table for the thread-specific data blocks. The outcome is endless recursion. The fix for the problem is simple - have either the allocation cache, the thread-specific data hash, or both, allocated off the system heap rather than the thread-specific allocation cache. Unfortunately, _Tcl\_InitCustomHashTable_ provides no way to accomplish this. # Proposal The _flags_ word in the _Tcl\_HashKeyType_ data structure shall be augmented with an additional value, _TCL\_HASH\_KEY\_SYSTEM\_HASH_. If this bit is set in the structure passed to _Tcl\_InitCustomHashTable_, then all memory allocated internally to manage the hash keys shall be obtained via direct calls to _TclpSysAlloc_, _TclpSysRealloc_, and _TclpSysFree_ rather than _Tcl\_Alloc_, _Tcl\_Realloc_ and _Tcl\_Free._ # Alternatives The authors considered and rejected the alternative of advancing _TCL\_HASH\_KEY\_TYPE\_VERSION_ and defining in the structure three new function pointers to allocate, reallocate, and free memory blocks. The additional complexity \(and associated performance degradation\) associated with dealing with two structure versions appeared to be unnecessary; it is difficult to imagine a situation where any allocator other than the system allocator or Tcl's own will be desired for the 'buckets' array, which varies widely in size. Custom small-block allocators make much more sense for the hash values than they do for the table of hash buckets. # Implementation Notes An implementation of this change is available from the SourceForge patch manager as item 731356. It is part of a larger overhaul of the thread-specific data manager. # Copyright This document is placed in the public domain. |
Name change from tip/139.tip to tip/139.md.
|
| < | | | | | | | < | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 139: Publish Part of Tcl's Namespace API Author: Donal K. Fellows <[email protected]> Created: 03-Jun-2003 Type: Project State: Final Vote: Done Tcl-Version: 8.5 Post-History: ----- # Abstract This TIP makes the simpler parts of Tcl's Namespace API available to the general C-coding public. # Rationale Tcl has had namespace support for a number of years now, ever since version 8.0. However, the C API for working with namespaces \(as opposed to the script-level [namespace] command\) has been hidden inside Tcl's private header files for all that time. This is mainly because of the complexity of some of the interfaces; name resolution is definitely difficult to document. But about half the API is not so encumbered, being the parts that deal with basic features like creation and destruction of namespaces themselves. It is these simpler parts that this TIP exposes as they have little risk of changing in the future, and I believe they should be made public particularly as it would allow extensions that create commands in namespaces to ensure the existence of the namespace first without resorting to applying _Tcl\_Eval_ to a small script. This TIP does not call for any alteration to the name, signature or behaviour of any API function at all. Note that these functions already have "public" names. # Exposed API Functions There are the following new public functions \(with signatures included for reference only\): Tcl\_CreateNamespace: Creates a new namespace. Tcl_Namespace * Tcl_CreateNamespace(Tcl_Interp *interp, CONST char *name, ClientData clientData, Tcl_NamespaceDeleteProc *deleteProc) Tcl\_DeleteNamespace: Deletes an existing namespace. void Tcl_DeleteNamespace(Tcl_Namespace *nsPtr) Tcl\_AppendExportList: Retrieves the export patterns for a namespace. int Tcl_AppendExportList(Tcl_Interp *interp, Tcl_Namespace *nsPtr, Tcl_Obj *objPtr) Tcl\_Export: Set/append to the export patterns for a namespace. int Tcl_Export(Tcl_Interp *interp, Tcl_Namespace *nsPtr, CONST char *pattern, int resetListFirst) Tcl\_Import: Import commands matching a pattern into a namespace. int Tcl_Import(Tcl_Interp *interp, Tcl_Namespace *nsPtr, CONST char *pattern, int allowOverwrite) Tcl\_ForgetImport: Remove imports matching a pattern. int Tcl_ForgetImport(Tcl_Interp *interp, Tcl_Namespace *nsPtr, CONST char *pattern) Tcl\_GetCurrentNamespace: Retrieve the current namespace. Tcl_Namespace * Tcl_GetCurrentNamespace(Tcl_Interp *interp) Tcl\_GetGlobalNamespace: Retrieve the global namespace. Tcl_Namespace * Tcl_GetGlobalNamespace(Tcl_Interp *interp) Tcl\_FindNamespace: Search for a namespace. Tcl_Namespace * Tcl_FindNamespace(Tcl_Interp *interp, CONST char *name, Tcl_Namespace *contextNsPtr, int flags) Tcl\_FindCommand: Search for a command and return its token, optionally in a namespace. Note that command tokens are already returned from _Tcl\_CreateCommand_ and _Tcl\_CreateObjCommand_ so this is not a new type of result. Tcl_Command Tcl_FindCommand(Tcl_Interp *interp, CONST char *name, Tcl_Namespace *contextNsPtr, int flags) Tcl\_GetCommandFromObj: Get a command token given a name. Tcl_Command Tcl_GetCommandFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr) Tcl\_GetCommandFullName: Get the full name of a command from its token. void Tcl_GetCommandFullName(Tcl_Interp *interp, Tcl_Command command, Tcl_Obj *objPtr) Each of these functions will be declared in future within _tcl.decls_ \(with the entries in _tclInt.decls_ deprecated\) and will also be documented. # Copyright This document is placed in the public domain. |
Name change from tip/14.tip to tip/14.md.
|
| < | < | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | < > | | | | | | | > | 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 | # TIP 14: Access to Tk Photo Image Transparency Author: Donal K. Fellows <[email protected]> State: Final Type: Project Vote: Done Created: 22-Nov-2000 Post-History: Keywords: Tk,photo,transparency,internal,access Tcl-Version: 8.4.0 ----- # Abstract It is useful for some code \(both extensions and scripts\) to have access to the transparency information in photo images for various reasons, but this is not currently available, even via an internal structure defined in _generic/tkInt.h_. This TIP is aimed at making the information available, and in such a way at the C level that backward compatibility is maintained in the future even if the internal structure definitions change. # Rationale I have been working for several years \(on-and-off\) on an extension for Tk that allows it to have non-rectangular windows \(<http://www.cs.man.ac.uk/~fellowsd/tcl/shapeidx.html\)> which is an effect that is great for all sorts of purposes but which comes particularly into its own when used in conjunction with drag-and-drop to make drag tokens that obscure only part of what lies underneath them. However, one of the most useful ways of specifying the shape of a window turns out to be via images of various kinds, and the natural way to do this is with the transparency data within the image. The problem is that this data is locked up entirely within structures that are completely private to _generic/tkImgPhoto.c_; none of it is visible at all anywhere else, even within the core. \(There is code that uses colour data instead to do this sort of trick, <http://www.sys.uea.ac.uk/~fuzz/tktrans/default.html,> but this is a slow process and frankly a little strange if we already have transparency data available.\) There is also a more general need for scripts to be able to discover more about the transparent areas of a photo image; at the moment, there is no access at all to that information at the script level. # Changes to the C-Level API To get around this problem, the data member _validRegion_ of the _PhotoMaster_ structure needs to be made available by some mechanism. There are two ways of doing this: 1. Placing the _PhotoMaster_ structure, or some version of it, in _generic/tkInt.h_, or 2. Creating a function to access the data member. The first way is very cheap initially, but also very inflexible and creates yet another hidden version dependency \(such as is tackled in [[5]](5.md)\) should we decide to change the structure for any reason \(we also have had problems with this sort of thing in the past in relation to the _Tcl\_Interp_ member _result_, direct access to which has been deprecated for years, but where there is still existing code that does it and which forms one of the largest barriers for some extensions from upgrading to Tcl 8.0 or later.\) It is also unnecessary since only the core needs to know how to create new instances of the structure. The second way, by contrast, is far more flexible in the future as it will allow us to completely change the internal implementation of photo image transparency without affecting any extensions at all. The cost of doing this is that a new entry in one of the stub tables must be created. Due to the fact that the type of the _validRegion_ member is \(currently\) internal, I propose adding the function to the _tkInt_ stub interface, and I propose calling the function _TkPhotoGetValidRegion_. # Changes to the Tcl-Level API I propose to add an extra subcommand to photo image instances which will provide all the access to and manipulation of transparency data. I propose to call this subcommand _transparency_ and it will have subsubcommands to provide access to the various facilities it provides. Initially I will provide a _get_ subsubcommand to allow the testing of the transparency of a single pixel \(returned as a boolean value\), and a _set_ subsubcommand to allow the setting of the transparency of a single pixel. I anticipate that these will be expanded in the future to allow the manipulation of transparencies of rectangular regions \(both getting and setting\) but I do not supply such at this stage. image create photo phImg -file thingy.gif if {[phImg transparency get 0 0]} { # Top-left pixel is transparent... } # Toggle transparency... phImg transparency set 0 0 [expr {![phImg transparency get 0 0]}] # Sample Implementation Patches Exposing the transparency to C: <http://www.cs.man.ac.uk/~fellowsd/tcl/validRegion.patch> Exposing the transparency to Tcl: <http://www.cs.man.ac.uk/~fellowsd/tcl/patches/transCmd.patch> # Copyright This document is placed in the public domain. |
Name change from tip/140.tip to tip/140.md.
|
| < | | | | | | < | | > | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 140: Tracing Namespace Modifications State: Deferred Type: Project Tcl-Version: 8.5 Vote: Pending Post-History: Author: Donal K. Fellows <[email protected]> Created: 04-Jun-2003 ----- # Abstract This TIP allows scripts to register callbacks to monitor alterations to namespaces, such as their deletion, the creation, renaming and deletion of commands within the namespace and modifications to the exports list of the namespace. # Rationale As part of my work on an experimental [[112]](112.md) implementation, I have discovered that computing the list of public \(i.e. exported\) commands from a namespace is a comparatively expensive operation. This means that it is necessary \(well, highly desirable\) to cache the list of exports from a namespace. But then I thought that it might be nice to expose that interface to use to better enable namespaces to support other interesting uses, and that it should be possible to implement the default behaviour in a Tcl script. It is in support of this that I present this TIP; I also add the ability to trace deletion of the namespace as a fairly obvious extension. # Proposed Change at Tcl Script Level I propose that the [trace] command be extended with a new type of thing to trace: a namespace. The operations that would trigger a trace are: * Namespace deletion \(subject to the same sorts of restrictions in relation to deleted interpreters that are present for traces of command deletion\) with the ops value _delete_. * Command list modification \(being creation, renaming or deletion of any command within that namespace\) with the ops value _command_. Modification due to deletion of the namespace will not trigger traces with this operation, but instead the _delete_ operation outlined above \(subject to the caveats relating to interpreter deletion.\) * Exports list modification \(i.e. updates with [namespace export]\) with the ops value _export_. Modification due to the deletion of the namespace will not trigger this traces with this operation, but instead the _delete_ operation outlined above \(subject to the caveats relating to interpreter deletion.\) In each case, the trace callback script will have the fully qualified name of the namespace and the name of the triggering operation appended to it before execution. In the case of command list modification by the _creation_ of a command \(which might also be through import of commands from another namespace, for example\) there will be an extra parameter being the _local_ name of the command \(without namespace separators.\) These changes will be propagated to each of the [trace add], [trace remove] and [trace info] subcommands, of course. # Proposed Change at C API Level Yet to be designed, but will be based as closely as possible on the existing Tcl trace APIs. # Copyright This document has been placed in the public domain. |
Name change from tip/141.tip to tip/141.md.
|
| < | < | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 141: Multiple Initial-Files in [tk_getOpenFile] Author: David N. Welton <[email protected]> State: Final Type: Project Tcl-Version: 8.5 Vote: Done Created: 18-Jul-2003 Post-History: ----- # Abstract This TIP proposes modifying the semantics of the **-initialfile** option when the **tk\_get\*File** commands are asked to select multiple files so as to allow several files to be selected initially. # Rationale The **tk\_getOpenFile** command has a **-multiple** option, which allows multiple files to be selected in the dialog. It also has an **-initialfile** argument. However, at the present time, at least on Unix, it is impossible to have multiple files selected initially with **-initialfile**. This TIP proposes that **-initialfile** take a list of files if **-multiple** is also passed as an argument. As it is possible to select multiple files, it should also be possible to have multiple files be selected when the widget is created via the **-initialfile** switch. ## Additional Notes from Kevin Kenny ### On -initialdir If the **-initialdir** value is not a well-formed path name in its filesystem \(for instance, if a component name contains a null byte or a character that is not permissible\), the behavior is as if **-initialdir** was not specified. If the object designated by the **-initialdir** value does not exist, or if it is not a directory, nor a symbolic link to one, the behavior is as if **-initialdir** was not specified. If the **-initialdir** value is the empty string, the behavior is as if **-initialdir** was not specified. ### On -initialfile If **-multiple** _0_ is specified, or **tk\_getSaveFile** was called, the **-initialfile** value is interpreted as a file name. If **-multiple** _1_ is specified to **tk\_getOpenFile**, the **-initialfile** value is interpreted as a list of file names. A list that is not well formed \(for example, one containing unbalanced braces\) is not an error, but instead causes the **-initialfile** option to be ignored. For each file name in the **-initialfile** value, the system joins the directory provided on the **-initialdir** option \(or the current working directory if no **-initialdir** is supplied\) with the **-initialfile**. The resulting path name is normalized as with **file normalize** and then separated into directory and tail components as with **file dirname** and **file tail**. Any errors in this process cause the file name to be ignored. Once the file name is separated into its components, the directory part is checked: * If the **-initialdir** option was supplied, and the directory part of the file name differs from the result of normalizing the **-initialdir** value, the file name is ignored. * If the **-initialdir** option was not supplied, and the directory part of the file name designates a directory in the file system, the **-initialdir** value is set to that directory. Otherwise, \(since the file cannot exist\), the file name is ignored. * If the given file exists, or if **tk\_getSaveFile was called**, the tail part of the file name is added to a list of files to select within the initial directory. Once **-initialdir** and **-initialfile** have both been parsed, the initial directory is known, and the list of initial files is identified; the files are known to be relative to the initial directory, and \(for **tk\_getOpenFile**\) are known to exist. # Reference Implementation The reference implementation exists in a patch <http://sf.net/tracker/?func=detail&aid=657656&group_id=12997&atid=362997> which also includes new tests for the Tk test suite and updated documentation. # Copyright This document is in the public domain. |
Name change from tip/142.tip to tip/142.md.
|
| < | < | | | | | | | | > | | | | | | | | < < > > | | | | < < | > > | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 142: Search Path Variable to Lookup Command Names in Namespaces Author: Ulrich Schoebel <[email protected]> Tcl-Version: 8.5 State: Withdrawn Type: Project Vote: Pending Created: 23-Jul-2003 Post-History: Keywords: namespace, command lookup, search path ----- # Abstract This TIP adds a Tcl variable to define the search path for command name lookup across namespaces. # Rationale Command names \(as well as variable names\) are currently looked up first in the current namspace, then, if not found, in the global namespace. It is often very useful to hide the commands defined in a subnamespace from being visible from upper namespaces by _info commands namespace::\*_. On the other hand, programmers want to use these commands without having to type a qualified name. * Example: namespace eval ns1 { proc p1 {} { puts "[p2]" } } namespace eval ns1::ns2 { proc p2 {} { return hello } } Evaluation of _ns1::p1_ would currently lead to an error, because _p2_ could not be found. Even worse, if a procedure _p2_ exists in the global namespace, the wrong procedure would be evaluated. # Proposal Add a variable _tcl\_namespacePath_ or, to avoid confusion with variables containing file system paths, _tcl\_namespaceSearch_, that contains a list of namespaces to be searched in that order. The default value would be _[list [namespace current] ::]_. In the above example _tcl\_namespacePath_ would be set to _[list [namespace current] [namespace current]::ns2]_. _p2_ would be found and not unintentionally be substituted by _::p2_. # Alternative For ease of implementation and, maybe, for programmers convenience it might be useful to always prepend the contents of this variable with _[namespace current]_. The programmer expects a certain "automatism" for this component of the search path. Then the default value would be _::_. # Implementation To be done when this TIP is accepted. # Notice of Withdrawal This TIP was Withdrawn by the TIP Editor following discussion on the tcl-core mailing list. The following is a summary of reasons for withdrawal: > Insufficiently subtle. 52 will break any code that assumes the current behaviour \(and you can bet someone will have that assumption\) and 142 doesn't let two namespaces have different search paths \(unless the variable is always interpreted locally, which just creates bizarre variable name magic.\) # Copyright This document is placed in the public domain. |
Name change from tip/143.tip to tip/143.md.
|
| < | < | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 | # TIP 143: An Interpreter Resource Limiting Framework Author: Donal K. Fellows <[email protected]> State: Final Type: Project Vote: Done Created: 25-Jul-2003 Post-History: Tcl-Version: 8.5 ----- # Abstract This TIP introduces a mechanism for creating and manipulating per-interpreter resource limits. This stops several significant classes of denial-of-service attack, and can also be used to do things like guaranteeing an answer within a particular amount of time. # Rationale Currently it is trivial for scripts running in even safe Tcl interpreters to conduct a denial-of-service attack on the thread in which they are running. All they have to do is write a simple infinite loop with the **for** or **while** commands. Of course, it is possible to put a stop to this by hiding those commands from the interpreter, but even then it is possible to simulate the DoS effect with the help of a procedure like this \(which even under ideal conditions will take over three days to run\): proc x s {eval $s; eval $s; eval $s; eval $s} x {x {x {x {x {x {x {x {x {x {x {x {x {x {sleep 1}}}}}}}}}}}}}} The easiest way around this, of course, is the resource quota as used by heavyweight operating systems, perhaps combined with the _alarm\(2\)_ system call. Or at least that would be the way to do it if it wasn't for the fact that those are ridiculously heavy sledgehammers to take to this particular nut. Luckily we control the execution environment - it is a Tcl interpreter after all - so we can implement our own checks. It is this that is the aim of this TIP. ## Efficiency Efficiency of any resource monitoring system is naturally a major concern; it is relatively simple to create a resource monitoring system but quite a lot harder to arrange for that monitoring to be cheap enough that its use does not greatly impact on the general speed of the program \(in this case, Tcl.\) The costs of checking time limits in particular can be somewhat excessive because of the necessity of performing a system call to carry out the check, but if you're performing any action a lot, it can get costly. My strategy for limiting the impact upon performance is to provide a programmer-tunable per-limit parameter called the granularity. This specifies how often \(out of all the locations in the processing of the Tcl interpreter and bytecode engine\) the limits should be checked; the granularity is per-limit because there is this distinct difference in the cost of checking different kinds of limits, and the limits are tunable because the ideal frequency depends very largely on the code being limited. This can be combined with the fact that the test to see if _any_ limits have been turned on can be made extremely cheap \(i.e. just a comparison of a memory location to zero\) and it allows unlimited interpreters to perform at almost the same speed as before. # A Tcl API for Limit Control I propose to add a subcommand **limit** to the **interp** command and to the object-like interpreter access commands. It will be an error for any safe interpreter to call the **limit** subcommand; master interpreters may enable it for their safe slaves via the mechanism interpreter aliases, as is normal for security policies. The first argument to the **interp limit** command will be the name of the interpreter whose limit is to be inspected. The second argument will be the name of the limit being modified; this TIP defines two kinds of limits: time: Specifies when the interpreter will be prohibited from performing further executions. The limit is not guaranteed to be hit at exactly the time given, but will not be hit before then. command: Specifies a maximum number of commands \(see **info cmdcount**\) to be executed. The third and subsequent arguments specify a series of properties \(each of which has a name that begins with a hyphen\) which may be set \(if there are pairs of arguments, being the property name and the value to set it to\) or read \(if there is just the property name on its own\). If no properties are listed at all, all dictionary \(see [[111]](111.md)\) of all properties for the particular limit is returned. The set of properties is limit-specific, but always includes the following: -command: A Tcl script to be executed in the global namespace of the interpreter reading/writing the property when the limit is found to be exceeded in the limited interpreter. If no command callback is defined _for this interpreter_, the **-command** option will be the empty string. Note that multiple interpreters may set command callbacks that are distinct from each other; an interpreter may not see what other interpreters have installed \(except by running a script in those foreign interpreters, of course.\) The order of calling of the callbacks is not defined by this TIP. > Where a callback returns any kind of exceptional condition \(i.e. the result isn't TCL\_OK\) a background error is flagged up. -granularity: Limits will always be checked in locations where the _Tcl\_Async\*\(\)_ API is called, as this is called regularly by the Tcl interpreter \(with a few exceptions relating to event loop handling.\) However, the cost of just checking a limit can be quite appreciable \(it might involve system calls, say\) so this property allows the control of how frequently, out of the opportunities to check a limit, are such limits actually checked. If the granularity is _1_, the limit will be checked every time. It is an error to try to set the granularity to less than _1_. When an interpreter hits a limit, it first runs all command callbacks in their respective interpreters. Once that is done, the interpreter rechecks the limit \(since the command callbacks might have decided to raise or remove it\) and if it is still exceeded it bails out the interpreter in the following way: * A flag is set in the interpreter to mark the interpreter as having exceeded its limits. * The currently executing command/script in the interpreter is made to return with code TCL\_ERROR. \(This is superior to using a novel return code, as third-party extensions are usually far better at handling error cases!\) * The **catch** command will only catch errors if the interpreter containing it does not have the flag mentioned just above set. Similarly, further trips round the internal loops of the **vwait**, **update** and **tkwait** commands will not proceed with that flag set. \(Extensions can find this information out by using _Tcl\_LimitExceeded\(\)_; see below.\) No calls to **bgerror** should be made. * Once the execution unwinds out of the interpreter so that no further invocations of the interpreter are left on the call-stack, the flag is reset. The same is true if the limits are adjusted in any way. Note that attempting to execute things within the interpreter without raising the limits will result in the limit being hit immediately. When resource limits are being used, unlimited master interpreters should take care to use the **catch** command when calling their limited slaves. Otherwise hitting the limit in the slave might well smash the master as well, just because of general error propagation. But that is good practise anyway. ## Time Limits Time limits are specified in terms of the time when the limit will be hit. Setting the limit to the current time ensures that the limit will be immediately activated. Time limits have two options for specifying the limit. -seconds: This sets the absolute time \(in seconds from the epoch, as returned by **clock seconds**\) that the time limit is hit. If set to the empty string, the limit is removed. If no time limit is set, this option is empty when inspected. -milliseconds: This sets the number of milliseconds after the start of the second specified in the **-seconds** option that the time limit is hit. May only be set to the empty string if the **-seconds** option is empty and present, and may only be set to a numeric value if the **-seconds** option is unspecified or present and non-empty \(it is always safe to leave this option unspecified.\) If no time limit is set, this option is empty when inspected. Where a time-limited interpreter creates a slave interpreter, the slave will get the same time-limit as the creating master interpreter. ## Command Limits Command limits are specified in terms of the number of commands \(see **info cmdcount** for a definition of the metric\) that may be executed before the limit is hit. Command limits have the following extra option for specifying and inspecting the limit. -value: The number of commands \(integer of course\) that may actually be executed. If set to the empty string, the limit is removed, and when introspecting, unlimited interpreters return empty strings for this value. Where a command-limited interpreter creates a slave interpreter, the slave will get the command-limit _0_ after initialisation \(i.e. after the return from the call to _Tcl\_CreateSlave\(\)_\) and will be unable to execute and commands until the limit for the slave is raised. Master interpreters implementing security policies for safe interpreters might want to set such limits semi-automatically to something more useful by deducting command-executions from the creating interpreter to its new slave. # A C-level API for Limit Control It is also desirable for there to be a general C API for controlling resource limits. Not only does this provide control to extension authors that can't be easily smashed by Tcl scripts by accident, but it also makes implementation of the Tcl API to the limit subsystem easier to create as well. * int **Tcl\_LimitReady**\(Tcl\_Interp \*_interp_\) > Test whether a limit is ready to be checked according to its granularity rules. Result is boolean. Note that this is a cheap call. * int **Tcl\_LimitCheck**\(Tcl\_Interp \*_interp_\) > Test whether a limit has been exceeded. Result is boolean. Note that this call is potentially expensive \(checking a time limit requires a minimum of one system call.\) * int **Tcl\_LimitExceeded**\(Tcl\_Interp \*_interp_\) > Test whether the interpreter is in a state where a limit has been previously exceeded \(i.e. whether a previous call to **Tcl\_LimitCheck** had indicated that a limit had been hit\) and not yet reset \(by extending or removing the relevant limit.\) Result is boolean. Note that this is a cheap call. * int **Tcl\_LimitTypeEnabled**\(Tcl\_Interp \*_interp_, int _type_\) > Test whether the given type of limit is turned on. Result is boolean. Note that this is a cheap call. * int **Tcl\_LimitTypeExceeded**\(Tcl\_Interp \*_interp_, int _type_\) > Test whether the given type of limit has been hit \(in the notion of **Tcl\_LimitExceeded**\) and not yet reset. Result is boolean. Note that this is a cheap call. * void **Tcl\_LimitTypeSet**\(Tcl\_Interp \*_interp_, int _type_\) > Turn on the given type of limit. * void **Tcl\_LimitTypeReset**\(Tcl\_Interp \*_interp_, int _type_\) > Turn off the given type of limit. * void **Tcl\_LimitAddHandler**\(Tcl\_Interp \*_interp_, int _type_, Tcl\_LimitHandlerProc \*_handlerProc_, ClientData _clientData_, Tcl\_LimitHandlerDeleteProc \*_deleteProc_\) > Add a limit handler for the given type of limit and specify some caller context and a scheme for deleting that context. * void **Tcl\_LimitRemoveHandler**\(Tcl\_Interp \*_interp_, int _type_, Tcl\_LimitHandlerProc \*_handlerProc_, ClientData _clientData_\) > Remove a limit handler for the given type of limit. It is not an error to delete a limit that was not set; in that case, nothing is changed. * void **Tcl\_LimitSetCommands**\(Tcl\_Interp \*_interp_, int _commandLimit_\) > Set a limiting value on the number of commands, and reset whether the limit has been triggered. Does not enable the limit. * int **Tcl\_LimitGetCommands**\(Tcl\_Interp \*_interp_\) > Get the current limit on the number of commands. * void **Tcl\_LimitSetTime**\(Tcl\_Interp \*_interp_, Tcl\_Time \*_timeLimitPtr_\) > Set a limiting value \(copying it from the buffer pointed to by _timeLimitPtr_\) on the latest time that the code may execute, and reset whether the limit has been triggered. Does not enable the limit. The _usec_ field of the buffer should be in the range 0 to 999999. * void **Tcl\_LimitGetTime**\(Tcl\_Interp \*_interp_, Tcl\_Time \*_timeLimitPtr_\) > Get the current limit on the execution time, writing it into the buffer pointed to by _timeLimitPtr_. * void **Tcl\_LimitSetGranularity**\(Tcl\_Interp \*_interp_, int _type_, int _granularity_\) > Set the checking granularity for the given type of limit. * int **Tcl\_LimitGetGranularity**\(Tcl\_Interp \*_interp_, int _type_\) > Get the checking granularity for the given type of limit. Above, _type_ is either TCL\_LIMIT\_COMMANDS or TCL\_LIMIT\_TIME, _handlerProc_ is a pointer to a function that takes two parameters \(a ClientData and a Tcl\_Interp\*\) and returns void, and _deleteProc_ is a pointer to a function that takes a single parameter \(a ClientData\) and returns void. The key is that _handlerProc_s are called when a limit is hit \(they are used to implement the guts of the **-command** option\), and when the callback is deleted for any reason \(including a call to **Tcl\_LimitRemoveHandler** and deleting the limited interpreter\) the _deleteProc_ is called to release the resources consumed by the _clientData_ context. # Use Cases ## WebServices One use for this sort of code might be in a web-services context where it is important to return a message to some client code within some interval. Using an in-process limiting mechanism allows this to be implemented in a far more light-weight fashion, as the alternative would be to fork off a new small application server for each incoming request and it would be considerably more complex to have a scripted executive that decides \(possibly by examining the stack\) whether a failure to deliver an answer within bounds is serious, or whether some extra resources should be granted to allow execution to run to completion. Other high-performance server applications would also be likely to gain from this sort of thing. ## Profiling It is possible to use the limiting code \(and especially the script callbacks\) to write a Tcl profiler. Every time the limit runs out, the callback can examine the Tcl stack in the limited interpreter and then assign some more resources to last up until the next profile trap. ## Untrusted Code Execution As indicated earlier, these limits can be used to increase control over untrusted code running in safe interpreters. While it would be necessary to extend this to memory consumption for every aspect that could be impacted by some malicious code to be controllable, having control over the number of commands that may be executed and how long those commands may take gives a much higher degree of control than currently exists, and is thus a monotonic improvement. # Possible Future Directions There are some obvious other things that could be brought within this framework, but which I've left out for various reasons: call stack: We already do limiting of this, so bring that within this framework would be a nice regularisation. On the other hand, such a change would not be backward-compatible, and it might not be safe to perform the callbacks either \(especially as overflowing the stack is fatal in a way that overrunning on time is not.\) memory: Limiting the amount of memory that an interpreter may allocate for its own use would be very nice. But conceptually difficult to do \(what about memory shared between interpreters?\), expensive to keep track of \(memory debugging is known to add a lot of overhead, and memory limiting would be more intrusive\) and a really big change technically too \(i.e. you'd be rewriting a significant fraction of the Tcl C API to make sure that every memory allocation knows which interpreter owns it.\) open channels, file sizes, etc.: Most other things can be limited in Tcl right now without special support. # Implementation An example implementation of this TIP is available as a patch <http://sf.net/tracker/?func=detail&aid=926771&group_id=10894&atid=310894> . # Copyright This document is placed in the public domain. |
Name change from tip/144.tip to tip/144.md.
|
| < | < | | | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | < > | | | < < | > > | | | | | | | | > | 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 | # TIP 144: Argument Expansion Syntax Author: Peter Spjuth <[email protected]> Author: Donal K. Fellows <[email protected]> Author: <[email protected]> State: Withdrawn Type: Project Vote: Pending Created: 26-Jul-2003 Post-History: Obsoleted-By: 157 Tcl-Version: 8.5 ----- # Abstract This TIP proposes to add syntax in Tcl to perform argument expansion in a safe and efficient manner. # Introduction Many commands take a variable number of arguments and often you find yourself with those arguments in a list. This list must then be expanded into individual arguments to the command. This is currently done with eval: eval destroy [winfo children .] This is a bit obscure and also very error prone when the command becomes more complex. It is also inefficient and not object safe, why something specialised in doing this would be better. # Background See also [[103]](103.md). Please also see a summary of a poll of TCLCORE readers taken after [[103]](103.md) was rejected. <http://wiki.tcl.tk/9462> # Rationale For examples three statements are used. This is the eval version: eval destroy [winfo children .] eval button .b $stdargs -text \$mytext -bd $border eval exec \$prog $opts1 [getMoreopts] \$file1 \$file2 The eval version would be even more complex if the lists that are to be expanded are not known to be pure. To be really safe the last would be: eval exec \$prog [lrange $opts1 0 end] [lrange [getMoreopts] 0 end] \$file1 \$file2 With the proposed syntax they become: destroy {}[winfo children .] button .b {}$stdargs -text $mytext -bd $border exec $prog {}$opts1 {}[getMoreopts] $file1 $file2 The advantage of using syntax for this is that the command do not get obscured. In the examples destroy/button/exec is the most important information on each line and it gets to be first on the line. # Specification If a word starts with a pair of braces, "\{\}", and is followed by a non whitespace character it signifies argument expansion. The braces are removed and the rest of the word is parsed and substituted as any other word. The character after the removed "\{\}" counts as a first character in the rules about open braces and double quotes. After substitution, the word is then parsed as a list \(as if with _Tcl\_SplitList\(\)_ or _Tcl\_GetListFromObj_\) and each element of the list is added to the command being built as a separate word with no further parsing. Before executing the command any word to be expanded is treated as a list where each element becomes one separate argument to the command. _Note 1:_ A word should really start with \{\} to trigger expansion which means that words like these are not expanded: cmd "{}$temp" \{}[something] _Note 2:_ Expansion is typically most useful with words like: cmd {}$var {}[somecmd $arg] {}$arr([cmd $arg]) But things like this are also legal: cmd {}word {}$x,$y {}[foo]xy[apa] {}{apa bepa} # Motivating Examples Many of the examples that make this TIP the way it is come from either advanced usage of commands like [exec] or from Tk. Consider the case where you have lists of options for several external commands that are to be executed together in a pipeline. With expansion it becomes easy to execute such things: exec prog1 {}$optlist1 | prog2 {}$optlist2 | prog3 -staticOption As you can see, without expansion building this pipeline would be quite a complex task and would make what is going on much more obscure. With Tk, there are many examples. Here's one from the creation of lines on a canvas: set id [$canv create polygon {}$coords -fill {} {}$opts -tags {foo bar}] In this case, there is a fair amount of material before the coordinate list, some static options \(which act like defaults\) between the coords list and the user-supplied options list, and some further options \(which act like overrides for semantically-significant bits\) after that which need careful space handling. This also demonstrates why having a command with a list of expanding indices is not a good idea, since it is plain to see that ongoing maintenance might place extra non-expanding arguments in various places through the command. Another example demonstrates why having commands as well as variables expanded is a good idea: namespace eval my { variable defaults { -bg white -fg black } proc entry {path args} { variable defaults ::entry $path {}$defaults {}[platformOpts $::tcl_platform(platform)] {}$args } } This illustrates why just plain [concat] doesn't work, demonstrates that having a way to do commands can be very useful, and also shows that having multiple expansion operations in a row is potentially useful. A final example \(deleting discontiguous ranges of characters with a particular tag\) shows that this is not just useful in Tk for when creating widgets and canvas items: $text delete {}[$text tag ranges $tagToCleanUp] In this case, the obvious alternative: foreach {s e} [$text tag ranges $theTag] { $text delete $s $e } is wrong, because the positions of the tags move with each deletion \(by contrast, the [$text delete] operation is careful in this regard.\) # Reference Implementation Not done yet. # Copyright This document has been placed in the public domain. |
Name change from tip/145.tip to tip/145.md.
|
| < | < | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 145: Enhanced Tk Font Handling Author: Pat Thoyts <[email protected]> State: Final Type: Project Vote: Done Created: 31-Jul-2003 Post-History: Obsoletes: 64 Tcl-Version: 8.5 ----- # Abstract [[64]](64.md) suggests some improvements to font handling under windows. However, not all of this TIP appears to have been implemented and I believe this can be done better using the Tk named fonts mechanism. # Rationale Windows, and no doubt MacOS as well, provide a number of system defined fonts. These are fonts that may be configured by the end user and that all applications are expected to use. The list includes the menu font, the caption font, the tooltip font and others. Some of the special fonts have been given symbolic names but these are not available to dynamic inspection. This TIP proposes to make these fonts available using the named font mechanism as used by the **font create** command. This has some significant advantages. The set of special font names becomes available to the programmer using the **font names** command. The font configuration is available using the **font configure** command. Also there is already a scheme in place to update all widgets using a named font when that fonts configuration changes. It is now a simple matter of re-defining the system fonts on receipt of the WM\_SETTINGCHANGE message to have Tk properly reflect changes to the system-wide font selection. # Proposed Changes ## Generic changes The named font creation routine **CreateNamedFont\(\)** is to be exposed on the public API as **Tk\_CreateNamedFont\(\)**. Also, the code used to delete a named font should be factored out into an API function, **Tk\_DeleteNamedFont\(\)**. ## Windows Platform-Specific Changes A **TkWinSetupSystemFonts\(\)** function is to be created which obtains the font description for the system fonts and calls **Tk\_CreateNamedFont\(\)** appropriately. This needs to be called during font package initialization. The fonts are obtained using the Win32 _SystemParameters_ API and the set of defined stock object identifiers used with _GetStockObject_. The toplevel Windows message message handler function **WmProc** must handle the WM\_SETTINGCHANGE message by calling the **TkWinSetupSystemFonts\(\)** function. This must call **Tk\_DeleteNamedFont** and then **Tk\_CreateNamedFont** to properly re-define the font and to propagate this change to all Tk widgets concerned. The Tk wigets will properly handle the font update by calling their _WorldChanged_ procedures. ## Cross-Platform Concerns It seems likely to be useful to ensure that aliases are available for each platform for the set of system fonts. This is currently done for the Tk cursors and helps to ensure that a script written for one system will usefully operate on another platform. Tk currently guarantees that "_Courier_", "_Times_" and "_Helvetica_" will always be available and are mapped to something suitable. It has been proposed that these should really be "_monospace_", "_serif_" and "_sans-serif_". The CSS specification <http://www.w3.org/TR/REC-CSS2/fonts.html#generic-font-families> defines these plus "_cursive_" and "_fantasy_" but there seems no good reason to include these two names. ## System Defined Fonts ### Windows The current set of special font names that Tk defines under windows are as follows, all with -underline 0 -overstrike 0 -slant roman ansi -family {MS Sans Serif} -size 8 -weight normal ansifixed -family {Courier New} -size 10 -weight normal defaultgui -family {MS Shell Dlg} -size 8 -weight normal device -family System -size 10 -weight bold fixed -family {Courier New} -size 10 -weight normal oemfixed -family Terminal -size 9 -weight normal system -family System -size 10 -weight bold systemfixed -family Fixedsys -size 9 -weight normal These are: ansi, windows variable pitch system font; ansifixed, a monospace version of ansi; defaultgui, default GDI font for menus and dialog boxes; system, used for system..... We can additionally provide from Windows system settings TkCaptionFont -family {Trebuchet MS} -size 10 -weight bold TkIconFont -family Tahoma -size 8 -weight normal TkMenuFont -family Tahoma -size 8 -weight normal TkMessageFont -family Tahoma -size 8 -weight normal TkSmallCaptionFont -family Tahoma -size 8 -weight bold TkStatusFont -family Tahoma -size 8 -weight normal These are fairly obvious. The caption font appears in the window title bar, the icon font for desktop icons, message font for message boxes, menu font, small caption font is for toolbox-type dialogs with very thin title bars. Finally status font is the font used for tooltips and status bars. All these Tk\* fonts can be changed via the Windows Desktop properties dialog. ### Motif XmNbuttonFontList (for pushbuttons in dialogs) XmNlabelFontList (for labels) XmNtextFontList (for text entry fields) XmNdefaultFontList (for everything else) ### GNOME Gnome or GTK\+ documentation, but the Gnome 2.2 "Font Preferences" dialog lets you specify: Application font Desktop font Window title font Terminal font It appears that all GTK\+ UI controls use the same "Application" font. ### KDE KDE's font preferences dialog lists: General Fixed Width Toolbar Menu Window Title Taskbar ### Aqua Aqua defines the following <http://developer.apple.com/documentation/UserExperience/Conceptual/AquaHIGuidelines/AHIGFonts/index.html> : System font Emphasized system font Small system font Emphasized small system font Application font Label font Mini system font > The system font is used for text in menus, modeless dialogs, and titles of document windows [...] The small system font is used for informative text in alerts [...]. It is also the default font for headings in lists, for help tags, and for text in the small versions of many controls. If your application creates text documents, use the application font as the default for user-created content. The label font is used for labels with controls such as sliders and icon bevel buttons. If necessary, the mini system font can be used for utility window labels and text. Use emphasized system fonts sparingly. An alternative reference <http://developer.apple.com/documentation/Carbon/Reference/Appearance_Manager/appearance_manager/constant_15.html> lists: kThemeSystemFont kThemeSmallSystemFont kThemeSmallEmphasizedSystemFont kThemeViewsFont kThemeEmphasizedSystemFont kThemeApplicationFont kThemeLabelFont kThemeMenuTitleFont kThemeMenuItemFont kThemeMenuItemMarkFont kThemeMenuItemCmdKeyFont kThemeWindowTitleFont kThemePushButtonFont kThemeUtilityWindowTitleFont kThemeAlertHeaderFont kThemeSystemFontDetail kThemeSystemFontDetailEmphasized kThemeToolbarFont # Suggested Tk Font Aliases From all the above this TIP suggests that the following names be provided for all platforms and where possible these map to system defined fonts. TkDefaultFont: the default for all GUI items not otherwise specified. TkFixedFont: standard fixed width font TkMenuFont: used for menu items TkCaptionFont: used for window and dialog caption bars TkSmallCaptionFont: used for captions on contained windows or tool dialogs. TkIconFont: font in use for icon captions TkTooltipFont: a font to use for tooltip windows \(transient information windows\) # Implementation <http://sf.net/tracker/?func=detail&aid=780617&group\_id=12997&atid=312997> # Copyright This document is placed in the public domain. |
Name change from tip/146.tip to tip/146.md.
|
| < | < | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | < < < > > > | | | | | | | | | | | | | | > | 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 | # TIP 146: Add Overall Anchoring to the Grid Geometry Manager Author: Peter Spjuth <[email protected]> State: Final Type: Project Vote: Done Created: 05-Aug-2003 Post-History: Tcl-Version: 8.5 ----- # Abstract This TIP proposes to add an anchor option to grid managers to control the behaviour of a grid where all weights are zero. # Rationale Have you ever found yourself adding "-weight" to an unused row or column in a grid? That is usually the workaround to use when you have no "-weight" on any column but you don't want things to sit in the middle of the grid when the window is grown. By adding an anchor option it lets the code directly reflect the intention of the programmer and it makes the code more maintainable since you can add and remove columns without having to update the dummy weight. # Shrinking a Grid When growing a grid, the behaviour is rather simple. Follow the weights and when 0, follow the anchor. When shrinking a grid without weight things get more interesting. The previous behaviour of the grid is a bit inconsistent in that when grown it centers the slaves \(as in anchor "center"\) and when shrunk it shows the upper left part \(as in anchor "nw"\). Thus, following the new anchor will not be backwardly compatible, even though I doubt it can be common for people to rely on that behaviour. For shrinking a grid without weight there are three options. 1. Always clip the bottom/right. i.e. behave as now. 2. Clip according to anchor. 3. Try to shrink all columns/rows, and only clip when minsize stops further shrinking. \(Clip according to anchor\) I think 2. makes more sense than 1., but it does mean a minor compatiblity breach. Also, with 2., behaviour 1. and 3. can be emulated but the other way around is harder. With 2, there are also two choises how to break compatibility depending on the default anchor. 2. a With default anchor _center_. Anyone relying on the bottom/left clipping will find things clip all around. Potentially an important widget in the nw corner can end up outside. 2. b With default anchor _nw_. Anyone relying on the centering will find things ending up in the nw corner. Probably just a visual difference. I can't see that any of those two are significantly worse than the other. Finally, the question "what would you do if backwards compatiblity was not an aspect?" clearly answers "2b", leading to the specification in this TIP. # Specification A new subcommand _grid anchor_ is added. It is similar to _grid propagate_ in that it configures an aspect of a grid manager. The syntax is _grid anchor master ?value?_ where _value_ is a standard anchor value with _nw_ as default. Whenever there is extra space in the grid manager and all weights are zero, the layout is placed within its master according to the master's anchor value. Whenever there is too little space in the grid manager and all weights are zero or all columns have reached their minimumn size, the layout is clipped according to the master's anchor value. # Shrink example To clarify the shrinking options here is an example. a: Current behaviour or, "1" with anchor "center". b: "2" with anchor "center" c: "2" with anchor "nw" d: "3" with anchor "nw" foreach top {.a .b .c .d} { toplevel $top frame $top.f for {set row 0} {$row < 2} {incr row} { for {set col 0} {$col < 4} {incr col} { set w $top.f.b${row}x$col button $w -text HejHopp grid $w -row $row -column $col } } } # Current behaviour pack .a.f -fill both -expand 1 # Anchor "center" with clipping place .b.f -relx 0.5 -rely 0.5 -anchor center wm geometry .b 150x50 # Anchor "nw" with clipping pack .c.f -side top -anchor w # Anchor "nw" with shrinking pack .d.f -side top -anchor w grid rowconfigure .d.f {0 1} -weight 1 grid columnconfigure .d.f {0 1 2 3} -weight 1 # Reference Implementation Not implemented yet. # Copyright This document has been placed in the public domain. |
Name change from tip/147.tip to tip/147.md.
|
| < | < | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 147: Make Grid's Column/Row Configure Easier Author: Peter Spjuth <[email protected]> State: Final Type: Project Vote: Done Created: 05-Aug-2003 Post-History: Tcl-Version: 8.5 ----- # Abstract This TIP proposes to add an alternative way to state which columns/rows in a grid are affected by an column/rowconfigure command. # Rationale Usually when doing a grid layout I tend to think in terms of what I want to do with a particular widget. For example a canvas or a frame that I want to expand within a resized window. Currently I need to translate that intention into a column and a row number to pass to column/rowconfigure. A more direct approach would be to pass the widget name directly to column/rowconfigure. Another situation is when all columns should be affected. Here I currently need to list them all \{0 1 2 3 4 5\}. Allowing an "all" keyword makes it easier and the code becomes more maintainable since you can add/remove columns without updating the list. What should be done when columnspan is greater than 1? There are three obvious possibilities: affect all, affect the first and affect the last. Any of these may be wanted by a programmer at one time or another so whatever is chosen, someone will be annoyed with it. Affecting all seems most logical. See also <http://sf.net/tracker/?func=detail&aid=659218&group\_id=12997&atid=362997> # Specification Anywhere _column_ is used below, the same applies to _row_ too. In the _index_ argument to _grid columnconfigure_, widget names and the keyword "all" is recognised besides the normal integers. When a widget name is used, it must be currently managed by the given _master_. The columns currently occupied by the widget are affected by the command. When the keyword "all" is used, all columns currently occupied by widgets in _master_ are affected by the command. _Note:_ "Currently occupied" means at the time of the invocation of the _grid columnconfigure_ command. The grid does not try to trace if a widget is moved in the grid or if more widgets are added. # Examples canvas .c scrollbar .sbx -orient horizontal scrollbar .sby -orient vertical grid .c .sby -sticky news grid .sbx -sticky we grid columnconfigure . .c -weight 1 grid rowconfigure . .c -weight 1 button .b1 -text a button .b2 -text b button .b3 -text example button .b4 -text xyzzy grid .b1 .b2 .b3 .b4 -sticky news grid columnconfigure . all -uniform a -weight 1 # Other Possibilities One possibility that is not proposed in this TIP is to also recognise the end-style indexing that indices in Tcl support \(through _TclGetIntForIndex\(\)_.\) Comment: "Personally, I think that end-index handling will be quite tricky since it would require knowing what the \*user\* thinks is the last column." # Reference Implementation Not implemented yet. # Copyright This document has been placed in the public domain. |
Name change from tip/148.tip to tip/148.md.
|
| < | < | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 148: Correct [list]-Quoting of the '#' Character Author: Don Porter <[email protected]> State: Final Type: Project Vote: Done Created: 08-Aug-2003 Post-History: Tcl-Version: 8.5 ----- # Abstract This TIP proposes the correction of a long-standing bug in the [list]-quoting of the _\#_ character. # Background Tcl has a bug in its [list]-quoting function. The bug is recorded as Tcl Bug 489537 \(<http://sf.net/tracker/?func=detail&aid=489537&group\_id=10894&atid=110894\).> Briefly, one of the documented functions of [list] is quoting of arguments so the result can be passed to [eval] with each list element becoming exactly one word of the command to be evaluated. Consider the example script: # FILE: demo.tcl set cmdName [lindex $argv 0] proc $cmdName {} {puts Success!} set command [list $cmdName] puts "Evaluating \[$command]..." eval $command This script expects one argument on the command line, and should write _Success!_ to stdout. This script works correctly for most input: $ tclsh demo.tcl foo Evaluating [foo]... Success! $ tclsh demo.tcl "with space" Evaluating [{with space}]... Success! But it fails for any argument beginning with the _\#_ character: $ tclsh demo.tcl #bar Evaluating [#bar]... This is because, contrary to the documentation, [list] does not quote the leading _\#_ in a manner to make the list safe for passing to [eval]. The Tcl parser sees the unquoted _\#_ as the start of a comment. Starting in Tcl 8.3, optimizations for evaluation of _pure lists_ were added, making inconsistency due to _Tcl\_ObjType_ shimmering a new symptom of this bug. If we adapt the example script to remove the [puts] \(so that a _pure list_ is maintained\): # FILE: demo2.tcl set cmdName [lindex $argv 0] proc $cmdName {} {puts Success!} set command [list $cmdName] eval $command We get a script that actually works with the troublesome input: $ tclsh demo2.tcl #bar Success! This bug in [list]-quoting is present in all released versions of Tcl since and including Tcl 7.4. It may go back further. There is no question that Tcl's behavior disagrees with its documentation on this point. I believe the documentation to be correct. From that viewpoint, this is a bug, not requiring a TIP for fixing. Because the bug has been around for so long, though, it seems prudent to make the TIP proposal, if only as fair warning to those who might have bug-dependent scripts to fix. The particular fix proposed also adds a single _\#define_ to Tcl's public header file. A large number of tests have been added to the Tcl test suite in the HEAD, demonstrating this bug in several ways. # Proposal _Tcl\_ConvertCountedElement\(\)_ is modified to have the default behavior of quoting any leading _\#_ character in a list element. With this default quoting, any string representation of a list generated by Tcl will not begin with the _\#_ character, so cannot be mis-parsed as a comment. _Tcl\_ConvertCountedElement\(\)_ is also modified to recognize a new bit flag value in its _flags_ argument, _TCL\_DONT\_QUOTE\_HASH_, which is defined in Tcl's public header file so that it may be used by extensions. When the _TCL\_DONT\_QUOTE\_HASH_ bit is set in the _flags_ argument, _Tcl\_ConvertCountedElement\(\)_ will not quote the leading _\#_ character. Quoting of the leading _\#_ character is only necessary for the first element of a list. Those callers of _Tcl\_ConvertCountedElement\(\)_ that can be sure they are not generating the first element of a list can pass in the _TCL\_DONT\_QUOTE\_HASH_ bit to produce the simplest quoting required. The behavior of the _TCL\_DONT\_QUOTE\_HASH_ bit flag is added to the documentation. The _Tcl\_ConvertElement\(\)_ routine is similarly modified \(trivially, since it is just a wrapper\). All callers of _Tcl\_ConvertCountedElement\(\)_ in the Tcl source code are modified to use the _TCL\_DONT\_QUOTE\_HASH_ flag as appropriate, so that Tcl continues to generate as simple string representations of lists as possible that do not suffer from Bug 489537. # Prototype A patch implementing this proposal is attached to Tcl Bug 489537 at SourceForge. # Compatibility After acceptance of this patch, the string representation of some lists will change, though as little as possible while still fixing the bug. Scripts that perform string comparisons on lists may see different results. Notably, a test in a test suite that has a test body that generates a list, and then has an expected result as a string may see new test failures. The minimal quoting changes should keep this incompatibility to a minimum, but it may happen. Notably there are no such compatibility problems in either the Tcl or Tk test suites. Any such incompatibility in other test suites can be easily remedied by using [list] to generate the expected result. # Scope It has been observed by some Tcl users that [list] is used for two conceptually distinct purposes. First, adding quoting to list elements as required, so that element boundaries can be re-discovered from the string representation. Second, adding quoting so that the string representation can be passed to [eval] with the original element boundaries becoming the argument boundaries in the evaluation. One can imagine a Tcl where these two functions were separated. However, this TIP does not propose such a separation, and further arguments on that point are out of scope, and should be considered in another TIP, if at all. # Acknowledgements The author acknowledges the discovery of this bug by Joe English, analysis by Donal Fellows, and a first draft patch from Miguel Sofer. # Copyright This document has been placed in the public domain. |
Name change from tip/149.tip to tip/149.md.
|
| < | | | | | | | < | > | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 149: Allow "enabled" as Synonym for "normal" in -state Option Author: Michael A. Cleverly <[email protected]> State: Withdrawn Type: Project Vote: Pending Created: 13-Aug-2003 Tcl-Version: 8.5 Post-History: ----- # Abstract This TIP allows Tk widgets which have a configurable _-state_ option to accept _enabled_ as a synonym for _normal_. # Rationale Tk widgets which have a configurable _-state_ option have \(at a minimum\) _normal_ and _disabled_ states. In common usage, however, the antonym of _disabled_ is _enabled_, not _normal_. Even experienced Tcl/Tk programmers sometimes forget, though they usually won't come out and admit it explicitly. \(Cf. <http://groups.google.com/groups?th=66e286d7efc3bbb6\)> # Proposed Changes Modify all Tk widgets which have a configurable _-state_ option to accept _enabled_ as a synonym for _normal_. The value returned by a widget's _cget_ method would continue to be _normal_. The appropriate man pages and test suite will be updated to document and test the use of _enabled_ as a synonym. % $w configure -state enabled % puts [$w cget -state] normal # Implementation A reference implementation will be provided shortly. # Copyright This document is placed in the public domain. |
Name change from tip/15.tip to tip/15.md.
|
| < | < | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 15: Functions to List and Detail Math Functions Author: Donal K. Fellows <[email protected]> State: Final Type: Project Vote: Done Created: 22-Nov-2000 Post-History: Keywords: Tcl,expr,function,introspection Tcl-Version: 8.4.0 ----- # Abstract Provides a way for the list of all math functions defined in the current interpreter to be discovered, and for discovering what arguments might be passed to an existing math function. This may be useful in tests as well as more general use. # Rationale Although it is quite easy to define a new function for use in expressions, there is no public way of performing introspection on this information. Having a way to extract the arguments from an existing math function was requested by <http://sourceforge.net/bugs/?func=detailbug&bug\_id=119304&group\_id=10894> and once you have one, it becomes trivial to also ask for a second function to list what functions are defined. I propose the creation of two functions that fulfil this rôle; _Tcl\_GetMathFuncInfo_ and _Tcl\_ListMathFuncs_. These functions will be documented on the same manual page as _Tcl\_CreateMathFunc_ and implemented in the same file. Furthermore, I also propose that the _info_ command in the Tcl interpreter be extended to include a new subcommand, _functions_, which will allow Tcl scripts to discover the list of installed functions \(by acting as a thin veneer over _Tcl\_ListMathFuncs_.\) Note that this is an extension of the _info_ command because it allows for introspection of a system that affects the behaviour of several commands that form the core part of the command-set: _expr_, _for_, _if_ and _while_. # Tcl\_GetMathFuncInfo This function will take an interpreter reference, a function name \(as a string\) and pointers to variables capable of taking each of the last four arguments to _Tcl\_CreateMathFunc_, and will return a standard Tcl result \(either _TCL\_OK_ or _TCL\_ERROR_, depending on whether a function with the given name exists within the given interpreter, with an error message being left in the interpreter's result in the _TCL\_ERROR_ case.\) The array of argument types whose reference is placed into the variable pointed to by _argTypesPtr_ will be allocated by Tcl, and should be freed with _Tcl\_Free_. int Tcl_GetMathFuncInfo(Tcl_Interp *interp, CONST char *name, int *numArgsPtr, Tcl_ValueType **argTypesPtr, Tcl_MathProc **procPtr, ClientData *clientDataPtr); The parameter names are chosen by analogy with _Tcl\_CreateMathFunc_. In the case where a math function is defined internally by the bytecode engine and has no standard implementation \(all the builtin functions in 8.4a2 are like this\) the value placed in the variable indicated by the _procPtr_ argument will be NULL. # Tcl\_ListMathFuncs This function will take an interpreter reference and an optional string that describes a glob-like pattern that restricts the set of math functions that the caller is interested in receiving \(with a _NULL_ indicating that no filtering is desired.\) The function will return a pointer to a newly-allocated _Tcl\_Obj_ list of the names of all the math functions defined within that interpreter, or _NULL_ in the case of an error \(in which case a suitable message will be left in the interpreter.\) The list will not be required to be sorted. Tcl_Obj *Tcl_ListMathFuncs(Tcl_Interp *interp, CONST char *pattern); The alternative is to pass in the addresses of variables that will be updated to contain the number of functions and an array of function names. But I prefer the _Tcl\_Obj_ approach as it is expressing the fact that the list of function names is really a single thing being returned \(albeit one that is not a simple value.\) It is not anticipated that the performance of this function will need to be crucial to too many applications. # info functions This new subcommand will provide access from Tcl scripts to the functionality of _Tcl\_ListMathFuncs_. It will take a single optional argument consisting of a pattern to pass on as the _pattern_ argument \(with the absence of the argument indicating that NULL is to be passed instead.\) # Copyright This document is placed in the public domain. |
Name change from tip/150.tip to tip/150.md.
|
| < | | | | | | < | | | > | | | | | | | | | | | | | | | > | 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 | # TIP 150: Implement the Tk send Command for Windows Author: Pat Thoyts <[email protected]> Type: Project State: Deferred Vote: Done Tcl-Version: 8.5 Keywords: tk, send Created: 25-Jul-2003 Post-History: ----- # Abstract This TIP proposes to provide an implementation of the send mechanism for Tk under Windows. # Rationale The Tk send command is used to provide an X server based mechanism for transmitting information between Tk applications. This provides the basis for remote introspection \(tkinspect\) and remote control \(tkcon\). This subsystem has never been implemented under Windows although there are means to emulate this using Tcl's dde package or the comm library. By providing a win32 implementation we help to standardise the Tk command set across platforms and will make it simpler to use this feature from Perl/Tk and Python Tkinter. # Reference Implementation This implementation is based upon an integrated version of the winsend package currently at <http://tclsoap.sf.net/winsend/.> This uses the Windows Running Object Table to maintain interpreter registration information. This is a global system COM object that is provided as part of the Windows COM automation framework. Its purpose is to provide a single registry for maintaining references to active COM components. When _tk appname_ is called a COM component is created which contains a reference to the Tcl interpreter. This is then registered with the Running Object Table with the registration name containing the Tk app-name. To find available interpreters we use the _winfo interps_ command. This iterates over all the registered objects looking for Tk registered names and can then return a list of registered interpreters. The Tk _send_ command is then provided as a COM method call. To perform a send, the client interpreter \(or indeed any automation capable COM client\) obtains the interpreter reference from the running object table and calls the _Send_ method on this object, passing in the command as a string. For the synchronous version this is sufficient. The result is returned using the standard COM method calling and error information can be returned the same way. Support for the asynchronous send is currently underway but will be modelled closely on the X-based asynchronous send. There are some advantages in using COM over DDE for the transport mechanism. DDEML has a tendency to use broadcast window messages. If there are any toplevel windows that are not processing their message queues, then DDE gets hung. While a fix has been applied to the Tcl dde package, there remain problems. In contrast the COM-based system never broadcasts. We initiate a conversation with the Running Object Table first and then with the specific application requested. If this application fails to process its message queue then we will get stuck - but no other poorly behaved application can affect our communication. A second advantage is than non-Tcl automation capable clients can also call our method. This means that Windows Scripting code \(vbscript or jscript\) can make use of the send command. Finally, given a suitable DCOM environment it should also be possible to implement the -displayof feature via Distributed COM. However, I don't see much call for this - network sockets are a lot simpler to use than DCOM. # Copyright This document is placed in the public domain. |
Name change from tip/151.tip to tip/151.md.
|
| < | < | | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 151: Remove -e: Command Line Option from tclsh and wish Author: Don Porter <[email protected]> Author: Don Porter <[email protected]> Author: Donal K. Fellows <[email protected]> State: Final Type: Project Vote: Done Created: 22-Aug-2003 Post-History: Tcl-Version: 8.5 ----- # Abstract This TIP proposes removal of the -e: command line option to tclsh and wish that was Accepted as part of [[137]](137.md). # Background [[137]](137.md) was Accepted today. However, there were a few NO votes objecting to the new _-e:_ form of the _-encoding_ command line option for specifying the encoding of a startup script to tclsh and wish. Those voting NO only objected to that part of [[137]](137.md) while supporting the rest as a solid proposal that will improve Tcl. Among those voting YES, no one explicitly embraced the _-e:_ command line option as something they required. Some voting YES opined that the _-e:_ option was a wart that could be fixed later. Based on those comments, [[137]](137.md) would have been better had the _-e:_ form of the command line option not been part of the proposal. This TIP proposes nothing more than removing Acceptance of the _-e:_ form of the _-encoding_ command line option. Without the controversial _-e:_ proposal, I believe [[137]](137.md) would have had unanimous approval. # Rationale The use of _-e:_ as a command line option to tclsh or wish suffers when compared with the perl program. The _perl -e_ option for evaluation of a Perl script provided on the command line is very well known, and it's a mistake to add something to tclsh that looks similar, but is in fact very different. [[137]](137.md) proposed both _-encoding_ and the _-e:_ form. There's really no need to add multiple ways to do the same thing. The Rationale in [[137]](137.md) for the _-e:_ form is solely to support the 32-character limit in some Unices for their _\#!_ lines. However, the _-e:_ form does not really solve that problem. For example: #!/usr/local/bin/tclsh8.5 -e:iso8859-15 12345678901234567890123456789012 Here we see that we still run afoul of the 32-character limit when tclsh is installed in the default location. Even longer encoding names exist which magnify the problem, and altering the installation location will not necessarily help: #!/usr/bin/tclsh8.5 -e:iso8859-15 12345678901234567890123456789012 \(This is actually an insidious failure mode in that it leads to the script being sourced with a valid but incorrect encoding.\) Conversely, we already have an effective general workaround for the 32-character limit problem: #!/bin/sh # \ exec tclsh -encoding iso8859-15 "$0" ${1+"$@"} So, _-e:_ doesn't solve a problem we don't really have, and it's controverisal. We should remove it. # Proposal Remove \(Acceptance of\) the _-e:_ set of command line options to the programs _tclsh_ and _wish_. # Compatibility Since no version of Tcl or Tk has been released supporting the _-e:_ command line option, there are no compatibility issues to resolve. # Copyright This document is placed in the public domain. |
Name change from tip/152.tip to tip/152.md.
|
| < | < | | | | | | | | | > | | | | | | | | | | | | | | > | 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 | # TIP 152: New -detail Option for tk_messageBox Author: Mats Bengtsson <[email protected]> State: Final Type: Project Tcl-Version: 8.5 Vote: Done Created: 26-Aug-2003 Obsoletes: 25 Post-History: Keywords: Tk ----- # Abstract This TIP proposes a new option for the **tk\_messageBox** for text that is less significant than the **-message** text. # Rationale Several platforms have a native feature of alert dialogs that includes messages with both a bold or large font, and a text in fine print, which gives more detail to the actual message. Both Mac OS 8/9 and Mac OS X include such a feature. This TIP suggests that this should be intruduced on all platforms, with the text to be displayed in that format specified using a new option **-detail**. In those cases where it is not straightforward to distinguish between the **-message** and **-detail** option contents, they should be combined into a single piece of text in a way that makes sense on the platform. # Reference Implementation The proposed change is now implemented as a loadable extension \(in C\) on Mac OS X <http://hem.fyristorg.com/matben/download/MovableAlerts.dmg> . The following images show the present \(8.4.4\) message box on AquaTk, and the proposed one. ![This is the present tk_messageBox.](../assets/152before.gif) ![{} This is the native tk_messageBox.](../assets/152after.gif) # Copyright This document has been placed in the public domain |
Name change from tip/153.tip to tip/153.md.
|
| < | < | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 153: Enhancing the [winfo toplevel] Command Author: Neil McKay <[email protected]> State: Final Type: Project Vote: Done Created: 26-Aug-2003 Post-History: Tcl-Version: 8.5 ----- # Abstract The [winfo toplevel] command returns the Tk toplevel window that encloses the window that's passed as an argument. However, Tk extensions may allow the creation of windows which reside at the top of a window hierarchy, but are not Tk toplevel widgets. If a subwindow of one of these top-of-hierarchy widgets is passed to [winfo toplevel], it returns an empty string, making it impossible to determine what hierarchy the window resides in. This TIP proposes enhancing the [winfo toplevel] command so that it will return the top window in the hierarchy regardless of what type of widget it is. # Rationale Focus control does not work properly for top-of-hierarchy Tk windows other than toplevel widgets. This is an artifact of Tk's inability to determine the top of a window hierarchy for such windows. Prior to Tk 8.4, top-of-hierarchy windows other than toplevels were not possible, so the changes proposed in this TIP would be moot. However, they are now possible due to the incorporation into the Tk core of the changes proposed in [[47]](47.md). As an example, consider the rootwin extension <http://www.eecs.umich.edu/~mckay/computer/rootwin0.4.tar.gz> . This extension adds a [rootwin] widget creation command, which turns an X display's root window into a Tk widget. The rootwin widget is a top-of-hierarchy widget, but is not an ordinary Tk toplevel. The command sequence rootwin .r entry .r.e place .r.e -x 100 -y 100 will create an entry widget near the upper left corner of the screen. However, it is impossible to type anything into the entry widget, because Tk's focus code does not work properly with rootwin widgets. The problem can be traced back to the fact that the command [winfo toplevel .r.e] returns the empty string. With the proposed extension, this command would return ".r", and the focus code would work properly. # Compatibility The proposed behavior for [winfo toplevel] is different from the current behavior, although only in the presence of Tk extensions that create top-of-hierarchy widgets that are not toplevels. The rootwin package is the only such extension known to this TIP's author, so the difference in behavior is unlikely to be noticed by anyone else. It should also be noted that the behavior \(prior to this TIP\) of [winfo toplevel] for top-of-hierarchy widgets that are not toplevels is not specified, so relying on its current behavior in such cicumstances is a questionable practice. # Implementation The core of the proposed change to [winfo toplevel] requires only a single-line change in file _generic/tkWindow.c_; however, the patch described below also changes the name of a function and changes some comments, to better describe the code's behavior. It also documents the new behavior in the [winfo] man page. # Patches A patch \(against Tk 8.4.5\) that implements the changes described above may be found at <http://www.eecs.umich.edu/~mckay/computer/winfotop.patch> # Copyright This document is in the public domain. |
Name change from tip/154.tip to tip/154.md.
|
| < | < | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 154: Add Named Colors to Tk Author: Damon Courtney <[email protected]> State: Draft Type: Project Vote: Pending Created: 03-Sep-2003 Post-History: Tcl-Version: 8.7 ----- # Abstract This TIP proposes the addition of a **color** command at the Tk level to allow developers to create named colors as they can already do with both fonts and images. # Rationale Named fonts and images go a long way toward making Tk able to modify a lot of options on a global scale simply by adjusting a single item. Tk already simulates some version of named colors on Windows with the use of values like _SystemButtonFace_ and _SystemWindowFrame_. These color names map to values pre-defined in Windows. On UNIX, we have to kind of fake these things around. With the addition of named colors, we can simply define default colors in UNIX that correspond to existing named colors on Windows. So, we could create _SystemButtonFace_ as a named color on UNIX, and any Windows program using those color names would port to UNIX without a change. # Implementation I propose the introduction of a new command, **color**: > **color** _option_ ?_arg ..._? This will have six subcommands. The **create** subcommand creates a new named color. > **color create** _colorName_ ?_option ..._? Supported options \(see below for full description\) are: -color: The main color associated with this named color. -dark1: The low-light color associated with this named color. -light1: The high-light color associated with this named color. The **cget** subcommand retrieves an option associated with a named color > **color cget** _colorName option_ The **configure** subcommand sets an option \(or options\) associted with a named color, or retrieves information about all the options associated with that named color \(following the standard Tk pattern for cget/configure.\) > **color configure** _colorName_ ?_option ..._? The **exists** subcommand determines if a named color exists. > **color exists** _colorName_ The **names** subcommand returns a list of all named colors, including those created by Tk. The optional glob-style _pattern_ allows only some colors to be returned. > **color names** ?_pattern_? The **delete** subcommand deletes a named color. > **color delete** _colorName_ ## Options The **-color** option specifies any acceptable color in Tk as the color to use. The **-light1** and **-dark1** options specify the border shadings to use for this color when it is used as a border. They are named with a 1 because I think in the future we will end up with more levels of shading. Windows already has two levels, we just ignore the second one. Beyond the color command, we need to implement a default set of standard colors that will exist across all platforms. As proposed by some, I think these should be named Tk\*. The current list \(reflected in the Windows color list\) would be: TkButtonFace TkButtonText TkDisabledText TkHighlight TkHighlightText TkMenu TkMenuText TkScrollbar TkWindow TkWindowFrame TkWindowText If there are others, I'm not sure what they are. This list can easily be expanded over time as most of them will be created at the Tcl-level. As part of this TIP, the core widgets should also be modified to use the new Tk\* named colors as their defaults for all platforms. The named colors will still be created from system defaults on each system. The UNIX colors will most likely come from whatever comes out of [[172]](172.md). # Copyright This document has been placed in the public domain. |
Name change from tip/155.tip to tip/155.md.
|
| < | < | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | < > | | | < > | | | < | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | < < > > | | | | < < | > > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 | # TIP 155: Fix Some of the Text Widget's Limitations Author: Vince Darley <[email protected]> State: Final Type: Project Vote: Done Created: 08-Sep-2003 Post-History: Tcl-Version: 8.5 ----- # Abstract Tk's text widget is very powerful, but has a number of known limitations. In particular the entire handling of wrapped lines and 'display/visual entities' versus 'logical entities' is quite limited. The most obvious side-effect of these inadequacies is the 'scrollbar problem' \(in which, particularly when there are long wrapped lines in the widget, the vertical scrollbar slider changes in size depending on the number of logical lines currently displayed, see <http://mini.net/tcl/896> for example\). This TIP overhauls the widget to provide consistent, complete support for 'display lines', 'display indices' and as a consequence smooth, pixel-based scrolling. A few other small bugs/issues have also been resolved. # Proposal The text widget has a number of limitations: 1. The aforementioned scrollbar interaction is flawed 1. To count the number of characters between index positions $idx1 and $idx2, one can only really do _string length [.text get $idx1 $idx2]_. There is no easy way to determine the number of visible \(non-elided\) characters between these two index positions, nor the number of valid index positions between them \(remember that embedded windows or images always take up one unit of index position, but don't correspond to any characters\). A similar difficulty exists in counting the number of display lines between two index positions, and in counting the number of pixels between two index positions \(or in the entire widget\). 1. Performing a correct text "replace" operation \(as used by a text editor, for example\) is difficult, because combinations of insert/delete tend to make the window scroll and/or leave the insertion cursor in an unnatural place. 1. There is no way to configure the widget to get an acceptable block-cursor. 1. When long lines are wrapped there is no easy way to get the beginning or end of a possible display line, or move up or down by display lines, unless the line is actually currently displayed \(and even then the code is rather complex\). 1. Even though 'search' can operate optionally on all text or just non-elided text, there is no easy way to retrieve the actual string which matched in the latter case, if the match spans characters on either side of an elided range. 1. _.text search -backwards -all_ returns subsets of indices in forwards rather than backwards order; with simple multi-line greedy searches \(like _-nolinestop -- .\*_\) it fails to match multiple lines; it can return backwards matches which fully enclose each other, etc. This TIP is, therefore, to fix these limitations, as follows: 1. Make internal changes to the text widget so it keeps track of the number of vertical display pixels in each logical line, and uses that information to calculate scrollbar interactions, to provide a better user experience, including smooth scrolling. This requires an extension to the text widget's yview command to do smooth scrolling: _.text yview scroll N pixels_ 1. Add a _count_ widget subcommand, which calculates the number of characters or index positions or non-elided characters/index positions or lines or displaylines or x/y-pixels between two given indices. Similar extend _\+N chars_ to allow index calculations by chars, indices and elided or not. 1. Add a _replace_ widget subcommand, which performs a combined delete/insert operation while ensuring that the insertion position, vertical display position, and undo/redo information is correctly set. 1. Add a _-blockcursor_ configuration option which makes the widget use a rectangular flashing "block" rather than a thin beam for the insertion point. 1. Add _displaylinestart_ and _displaylineend_ and _\+/- N displaylines_ index offsets which work like _linestart_, _lineend_, _\+/- N lines_ but with display lines, and which work whether the relevant indices are currently displayed or not. And make _tk::TextUpDownLine_ operate in terms of display lines. 1. Add an option _-displaychars_ to _get_ which, if given, restricts the returned characters to be just those which are not elided. 1. Fix 'search -all -backwards' so that it returns the matches in the correct backwards sequence, even within each individual line. Also add the options '-overlap' \(to allow matches which overlap each other to be returned\) and '-strictlimits' to prevent matches which would extend beyond the strict [pos,limit] range. Fix code for correct greedy forwards and backwards searches using correct non-overlapping matching unless explicitly requested. Each of these proposals is discussed and presented in full detail below. In addition, the current implementation provides for a bit more text widget objectification and fixes the "very slow deletion of lots of text with lots of tags" bug \(there was a non-linear slowdown which has been removed\). One crashing bug in the text widget has also been fixed, and a bug in searches with '-all'. # Scrollbar Interaction This is the most complex of the proposed changes, even though solving it results in very limited changes to the actual text-widget's public Tcl or C interfaces. The following example illustrates the problem: pack [scrollbar .s -command {.t yview}] -side right -fill y pack [text .t -yscrollcommand {.s set}] -side left for {set i 0} {$i < 300} {incr i} { .t insert insert $i } for {set i 0} {$i < 20} {incr i} { .t insert insert "$i\n" } for {set i 0} {$i < 300} {incr i} { .t insert insert $i } Solving this problem perfectly must require the text widget to know exactly how many vertical pixels each line contains. However, for a widget which contains a great deal \(megabytes\) of text, images, embedded windows and numerous tags \(and on which certain tags could have their font configuration changed on the fly\), it is clearly impractical to have the widget calculate every line's pixel-height requirements whenever anything changes \(for bad cases the response-time would be unacceptable\). The solution proposed is an asynchronous update mechanism where the structure representing each logical line caches the last known pixel height and an epoch counter. As changes \(global or local\) are made, individual logical lines recalculate their height either immediately \(for small, local changes such as inserting a few characters\) or are scheduled for recalculation \(for larger changes such as resizing the window or changing size-influencing tag settings\). When blocks of lines \(or, indeed, all lines\) are scheduled for recalculation, each asynchronous callback should only recalculate the pixel heights of a relatively small number of lines, so that user-responsiveness is maintained. As line pixel-height calculations are updated, a second asynchronous mechanism is triggered, this one to update any scrollbar attached to the text widget \(i.e. call the _-yscrollcommand_ callback\). Again it is undesirable to call this every single time a single line's height is updated, so this is called with a timer mechanism so it is updated every 200ms. Both of these asynchronous mechanisms should be designed so they do not need to be run if nothing relevant has changed in the widget. It may require some experimentation to determine the most appropriate usage patterns of these asynchronous callbacks. In particular, the current implementation uses timer callbacks \(idle callbacks cannot be used because idle callbacks are not allowed to reschedule themselves\). A thread-based implementation may have some advantages \(although it certainly has disadvantages too\). Given the pixel calculations are available, they have been used to provide for smooth scrolling of the text widget. This means even with large images \(possibly even larger than the height of the widget itself\), smooth scrolling off top and bottom of the widget are automatic. In order for smooth scrolling to be used by Tk's Tcl library, the _pixels_ unit has been added to the _.text yview scroll_ command. This is used to ensure mouse-wheel and scan-drag scrolling are smooth. It is important that the existing _pages_ and _units_ \(the latter being display lines\) do not change in meaning so that, for example, clicking on a scrollbar's arrow still scrolls the widget by 1 display line. # Count Subcommand A new subcommand _.text count ?options? startIndex endIndex_ is added for all text widgets. Valid options \(any combination of which can be specified\) are _-chars_, _-indices_, _-displaychars_, _-displayindices_, _-lines_, _-displaylines_, _-xpixels_, _-ypixels_. The default value, if no option is specified, is _-indices_. In addition _-update_ can be specified. If given this option ensures all subsequent options operate on a range of indices for which all metric calculations \(e.g. line pixel heights\) are up to date. This option is of particular importance to the _-ypixels_ option. The subcommand counts the number of relevant things between the two indices. If startIndex is after endIndex, the result will be a negative number. The actual items which are counted depend on the option given, as follows: -indices: count all characters and embedded windows or images \(i.e. everything which counts in text-widget index space\), whether they are elided or not. -chars: count all characters, whether elided or not. Do not count embedded windows or images. -displaychars: count all non-elided characters. -displayindices: count all non-elided characters, windows and images. -lines: count all logical lines \(this option is only included for completeness since it can be achieved pretty easily in Tk already\) -displaylines: count all displaylines. -xpixels: count the number of horizontal pixels between the two indices. -ypixels: count the number of vertical pixels between the two indices. If more than one of these counting options is given, the result is a list with one entry for each such option given \(_-update_ does not contribute to this result, of course\). Similar, the index modifiers are extended so the following are now valid: "\+N display chars", "\+N indices", "\+N display indices", "\+N any indices", "\+N any chars". The "display" and "any" can be abbreviated if they are followed by whitespace. In particular, this means that: string length [.text get $i1 $i2] == [.text count -chars $i1 $i2] provided $i1 is not after $i2 in the widget. It also means that .text compare "$i1 + [.text count -indices $i1 $i2]indices" == $i2 and .text compare "$i1 + [.text count -displayindices $i1 $i2] display indices" == $i2 is true under all circumstances. Lastly, for those who wish to know the required number of vertical pixels a text widget needs, _.text count -update -ypixels 1.0 end_ will give this \(once any borderwidth, highlightthickness and ypad have been added on\). For example, the following procedure will give the smallest possible size in pixels which a given text widget would desire to have no scrollbars: proc textDetermineDimensions {text} { set border [$text cget -highlightthickness] incr border [$text cget -borderwidth] set y [expr {2* ($border + [$text cget -pady])}] set x [expr {2* ($border + [$text cget -padx])}] incr y [$text count -update -ypixels 1.0 end] if {[$text cget -wrap] eq "none"} { set max_x 0 for {set i 0} {$i < int([$text index end])} {incr i} { set xpix [$text count -xpixels ${i}.0 "${i}.0 linend"] if {$xpix > $max_x} { set max_x $xpix } } incr max_x $x return [list $x $y] } else { return [list [winfo reqwidth $text] $y] } } # Replace Subcommand A new subcommand .text replace index1 index2 chars ?tagList chars tagList ...? is added for all text widgets. This subcommand is approximately equivalent to a combined: .text delete index1 index2 .text insert index1 chars ?tagList chars tagList ...? but also ensures that the current window display position \(e.g. what line is currently displayed at the top left corner of the text widget\), the current insertion position and the undo/redo stack are all correctly set up. This subcommand could be implemented in pure Tcl, but is quite complex to get right. The C-level implementation shares most of the code with insert/delete/count and can also be made more efficient in its handling of window-scrolling issues. # Block Cursor A new text widget configuration option _-blockcursor <boolean>_ is added. If set to any true value, instead of a thin flashing vertical bar being used for the insertion cursor, a full rectangular block is used instead. # Display-Line Handling Currently one can discover the beginning or end of a given logical line and move between logical lines with: .text index "$idx linestart" .text index "$idx lineend" .text index "$idx +1lines" .text index "$idx -5lines" However, when a given logical line may be wrapped over numerous display lines it is not so simple to find the beginning or end of a display line, or move up or down by display lines. \(In fact is is currently possible with the _@_ syntax if the logical line and the $idx are both currently displayed on screen, but is not possible\(\*\) if the logical line is not currently displayed\). Therefore a new index manipulation set are added: .text index "$idx display linestart" .text index "$idx display lineend" .text index "$idx +1display lines" .text index "$idx -5display lines" These work whether or not $idx is currently displayed \(when it is not displayed, the index is calculated by laying out the geometry of the line behind the scenes so this operation is certainly more time-consuming than determining the logical line start or end\). The "display" in these items can be abbreviated if it is followed by whitespace \(if it is not abbreviated then the whitespace is optional\). In addition the single Tcl proc _tk::TextUpDownLine_ \(in text.tcl\) has been updated to operate in terms of display lines and thereby to retain the current x position as accurately as possible across multiple up/down arrow keypresses. \(\*\) Perhaps it would be possible, if horribly cumbersome, by copying the relevant contents into another text widget which is unmapped and making sure the desired lines are visible in that widget, and finally performing the desired operations on the copy before deleting it all! # Get -displaychars This is a simple new option to the _get_ subcommand, which now has the syntax _.text get ?-displaychars? ?--? index1 ?index2....?_. This means the following code now makes sense: set found [.text search -elide -count num $pattern $pos] set match [.text get -displaychars $found "$found + $num chars"] Previously, achieving something like the second line was quite complex. # Search subcommand In Tk8.5a0 at present _search -all -backwards ..._ returns the list of indices backwards from line to line, but forwards within each line \(a side-effect of backwards matching being implemented as repeated forward searches\). Large backwards or forwards regexp searches for, say, _-nolinestop -- .\*_ would only match a single line. Various other overlap vs non-overlap problems too. All of these glitches \(my own code ;-\) have been fixed and the test suite for _search_ hugely extended. # Backward Compatibility All of the above changes simply extend the functionality of the text widget in new ways, and therefore have no significant backward compatibility problems. It is possible that some existing Tk code may notice some minor behavioural differences: Since the interaction between text widget and vertical scrollbar is now slightly different, any code which assumed that a particular scrollbar position \(e.g. 0.5\) corresponds to a particular line of text will find that that line of text may now be different \(and will of course depend on the actual line heights\). This change is considered a bug fix, not an incompatibility! In particular, however, any code which performs a calculation like: set num_lines [lindex [split [.text index end] .] 0] set last_visible [expr {int($num_lines *[lindex [.text yview] 1])}] \(under the assumption that the scrollbar's units are effectively measured in logical lines\) will now get a different answer \(since the scrollbar operates with pixels\), and that different answer will not correspond to the last visible line. Of course the code should always have used: set last_visible [expr {int([.text index "@[winfo width .text],[winfo height .text]"])}] which works correctly no matter how the scrollbar operates. In addition, with the new _pixels_ unit for the scrollbar, the command _.text yview scroll 1 p_ is now ambiguous and will throw an error. This incompatibility is similar to those which have previously been introduced in, e.g., Tk 8.4 \(with -padx, -pady\). Lastly, "\+N chars" is a synonym for "\+N indices" for backwards compatibility reasons. This may be different to "\+N any chars". # Implementation A complete implementation is available at: <http://sf.net/tracker/?func=detail&aid=791292&group\_id=12997&atid=312997> This passes all Tk text widget tests \(on Windows XP, at least\), including a significant number of new tests. The memory requirements of the text widget have increased marginally to support the correct vertical scrolling behaviour: two new integers must be stored for each logical line of text. # Out of Scope A number of other text widget enhancements might be nice. Some of these are listed here for completeness: * Printing support \(at least to postscript like the canvas widget -- in fact I'm sure 95% of the canvas printing code could be re-used for this, with the only new stuff being handling of multiple pages. It might be preferable to support pdf instead, however\) * Cloning \(e.g. reading in the result of _.text -dump_, although handling of tag definitions and tag-bindings would also be nice\) * Synchronizing/backing the widget contents with a Tcl variable \(actually not too hard to implement quite efficiently now, given the _count_ functionality\). This can be done without too much trouble with pure Tcl. * Loading data into the widget asynchronously from a channel \(easy to implement with Tcl procedures, although core support might make for better scrollbar handling and thereby make such a feature almost invisible to the user\). * Modifications to the horizontal scrollbar. The horizontal scrollbar's position/status depends only on the _currently-displayed contents_ of the text widget. This means as one scrolls the widget vertically, the horizontal scrollbar changes. No attempt has been made to fix this problem in this TIP. * A shorthand \(_display start_, _display end_?\) for the rather less obvious _.text index "@0,0"_ and _.text index "@[winfo width .text],[winfo height .text]"_ * The attachment of user-defined data to each logical line in the widget \(e.g. a code parser's current internal state\), which might make true parsing for syntax colouring significantly easier. * The pre-existing behaviour of _\+/- N lines_ uses byte-indices instead of x-pixel calculations \(thereby having the cursor bobbling around when there are multi-byte characters or even worse when there are images, proportional fonts, tabs, etc\). Further, the behaviour is quite strange when wrapping is enabled in the widget. This TIP does not propose any changes in this area other than to suggest that Tcl coders make use of 'displaylines' instead, for more consistent behaviour \(as has been done to text.tcl\). * To do word-matching with _search_ requires the use of a regexp pattern and something like _.text search -regexp -- "\\\\m[quote::Regfind $string]\\\\M" $pos_. It might be nice to add a flag to control word-matching without the need for such manipulations. None of these is included in the current TIP or current implementation. If interested members of the community wish to extend this TIP or submit further TIPs to handle any of these enhancements, they are very welcome \(and the author is happy to help coordinate where possible\). # Copyright This document has been placed in the public domain. |
Name change from tip/156.tip to tip/156.md.
|
| < | < | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 156: Language-Neutral Root Locale for Msgcat Author: Kevin Kenny <[email protected]> State: Final Type: Project Vote: Done Created: 20-Sep-2003 Tcl-Version: 8.5 Discussions-To: news:comp.lang.tcl Post-History: ----- # Abstract This TIP proposes to extend Tcl's message catalog mechanism by adding a "root locale" \(whose name is the empty string\) that is searched after searches in all the language-dependent locales have failed. # Rationale In the current message catalog system, the search key for localized strings is a version of the string itself, expressed in either a language-neutral form or in the natural language of the programmer. This scheme has the advantage that when a program searches for a localized message, the search will always succeed; if a translation of the message cannot be found in any of the message catalog preferences, at least a language-neutral string \(or a string in an inappropriate language\) will be available. The drawback to the scheme as it stands comes when ambiguities enter into the picture. For instance, the English word, 'file,' might, depending on context, appear in French as the word 'fichier,' or the word, 'râpe.' An application implementing a catalog of hand tools might well encounter such an ambiguity. A more specific example that I have encountered deals with date and time formatting. Consider the [clock format] command. It accepts a format group, %x, that formats the current date in the default format for the current locale. It also accepts a group, %D, that formats the current date in the specific format %m/%d/%Y. In both the 'C' locale and the 'en\_US' locale, these two format groups generate identical strings. If the message catalog is used to store them, there has to be a way to have distinct keys look up the same string in the language-neutral default locale. # Specification The solution that both Java and ICU use for managing the problem of ambiguity in the default locale is to implement a "root locale" that is searched after the searches in the current language-dependent locales have failed. If a translation is found in the "root locale", it is used just as if it was found in a language-dependent locale. This TIP proposes the same for Tcl. Specifically, it proposes that. 1. The _msgcat::mcpreferences_ command will be modified to add the empty string as a list element after the elements corresponding to the current locale. If the current locale, for instance, is _en\_US\_funky_, the result of [mcpreferences] will be _\{en\_US\_funky en\_US en \{\}\}_, and if the current locale is _de\_CH\_schwyzertuetsch_, the four locales to be searched will be: > \* _de\_CH\_schwyzertuetsch_ > \* _de\_CH_ > \* _de_ > \* \{\} \(the empty locale\) 2. The _msgcat::mcload_ command will be modified so that if it encounters the empty string as a locale name, it will replace it with ROOT. This modification is made so that the empty locale will correspond to a file named, "ROOT.msg" rather than just ".msg", and hence yield a file whose name does not begin with a period. Files whose names begin with periods are treated specially on certain filesystems \(for instance, on Unix, they become files hidden from the _ls_ command\), and avoiding such names seems wise. The implementors of both Java and ICU have made the same decision. # Reference Implementation The changes require to implement this proposal are minimal and can be obtained from SourceForge as Tcl Patch \#809825. # Copyright Copyright © 2003 by Kevin B. Kenny. All rights reserved. Permission to use this document in accordance with the terms of Open Publication License \(<http://www.opencontent.org/openpub/\)> is herewith granted. |
Name change from tip/157.tip to tip/157.md.
|
| < | < | | | | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | < > | | | | | < < | > > | | | | | | | | | | | | | | > | 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 | # TIP 157: Argument Expansion with Leading {expand} Author: Kevin B. Kenny <[email protected]> Author: Peter Spjuth <[email protected]> Author: Donal K. Fellows <[email protected]> Author: Don Porter <[email protected]> State: Final Type: Project Vote: Done Created: 20-Sep-2003 Post-History: Obsoletes: 144 Tcl-Version: 8.5 ----- # Abstract This TIP proposes to add syntax in Tcl to perform argument expansion in a safe and efficient manner. # Introduction Many commands take a variable number of arguments and often you find yourself with those arguments in a list. This list must then be expanded into individual arguments to the command. This is currently done with eval: eval destroy [winfo children .] This is a bit obscure and also very error prone when the command becomes more complex. It is also inefficient and not object safe, why something specialised in doing this would be better. # Background See also [[103]](103.md) and [[144]](144.md). Please also see a summary of a poll of TCLCORE readers taken after [[103]](103.md) was rejected. <http://wiki.tcl.tk/9462> # Rationale For examples three statements are used. This is the eval version: eval destroy [winfo children .] eval button .b $stdargs -text \$mytext -bd $border eval exec \$prog $opts1 [getMoreopts] \$file1 \$file2 The eval version would be even more complex if the lists that are to be expanded are not known to be pure. To be really safe the last would be: eval exec \$prog [lrange $opts1 0 end] [lrange [getMoreopts] 0 end] \$file1 \$file2 With the proposed syntax they become: destroy {expand}[winfo children .] button .b {expand}$stdargs -text $mytext -bd $border exec $prog {expand}$opts1 {expand}[getMoreopts] $file1 $file2 The advantage of using syntax for this is that the command do not get obscured. In the examples destroy/button/exec is the most important information on each line and it gets to be first on the line. # Specification If a word starts with the string, "\{expand\}", and is followed by a non whitespace character it signifies argument expansion. The leading "\{expand\}" is removed and the rest of the word is parsed and substituted as any other word. The character after the removed "\{expand\}" counts as a first character in the rules about open braces and double quotes. After substitution, the word is then parsed as a list \(as if with _Tcl\_SplitList\(\)_ or _Tcl\_GetListFromObj_\) and each element of the list is added to the command being built as a separate word with no further parsing. Before executing the command any word to be expanded is treated as a list where each element becomes one separate argument to the command. _Note 1:_ A word must begin with \{expand\} to trigger expansion which means that words like these are not expanded: cmd "{expand}$temp" \{expand}[something] _Note 2:_ Expansion is typically most useful with words like: cmd {expand}$var {expand}[somecmd $arg] {expand}$arr([cmd $arg]) But things like this are also legal: cmd {expand}word {expand}$x,$y {expand}[foo]xy[apa] {expand}{apa bepa} # Motivating Examples Many of the examples that make this TIP the way it is come from either advanced usage of commands like [exec] or from Tk. Consider the case where you have lists of options for several external commands that are to be executed together in a pipeline. With expansion it becomes easy to execute such things: exec prog1 {expand}$optlist1 | prog2 {expand}$optlist2 | prog3 -staticOption As you can see, without expansion building this pipeline would be quite a complex task and would make what is going on much more obscure. With Tk, there are many examples. Here's one from the creation of lines on a canvas: set id [$canv create polygon {expand}$coords -fill {} \ {expand}$opts -tags {foo bar}] In this case, there is a fair amount of material before the coordinate list, some static options \(which act like defaults\) between the coords list and the user-supplied options list, and some further options \(which act like overrides for semantically-significant bits\) after that which need careful space handling. This also demonstrates why having a command with a list of expanding indices is not a good idea, since it is plain to see that ongoing maintenance might place extra non-expanding arguments in various places through the command. Another example demonstrates why having commands as well as variables expanded is a good idea: namespace eval my { variable defaults { -bg white -fg black } proc entry {path args} { variable defaults ::entry $path {expand}$defaults \ {expand}[platformOpts $::tcl_platform(platform)] \ {expand}$args } } This illustrates why just plain [concat] doesn't work, demonstrates that having a way to do commands can be very useful, and also shows that having multiple expansion operations in a row is potentially useful. A final example \(deleting discontiguous ranges of characters with a particular tag\) shows that this is not just useful in Tk for when creating widgets and canvas items: $text delete {expand}[$text tag ranges $tagToCleanUp] In this case, the obvious alternative: foreach {s e} [$text tag ranges $theTag] { $text delete $s $e } is wrong, because the positions of the tags move with each deletion \(by contrast, the [$text delete] operation is careful in this regard.\) # Reference Implementation Not done yet. # Summary of Discussions This TIP has had a long history; a great many alternatives have been proposed - two \([[103]](103.md) and [[144]](144.md)\) formally. In a poll of TCT members conducted by one of the authors, this version appeared to be the most preferred. Much of the discussion is summarized at <http://aspn.activestate.com/ASPN/Mail/Message/tcl-core/1805934> and <http://aspn.activestate.com/ASPN/Mail/Message/tcl-core/1791605> \(much of the mailing list traffic between those two messages is devoted to discussion of this issue.\) An open issue remains as to which Tcl release is suitable for the implementation of this feature. The question will be resolved by voting on this TIP twice: once for 8.5 and once for 9.0 # Copyright This document has been placed in the public domain. |
Name change from tip/158.tip to tip/158.md.
|
| < | < | | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 158: Distinguish the two 'Enter' keys on Windows Author: Wolfgang Großbauer <[email protected]> Author: Kevin Kenny <[email protected]> State: Final Type: Project Vote: Done Created: 20-Sep-2003 Post-History: Discussions-To: news:comp.lang.tcl Tcl-Version: 8.5 ----- # Abstract This TIP proposes that the "extended keys" on a Windows keyboard be labeled with <Mod4> so that they can be distinguished from their counterparts on the main keyboard. # Rationale Most US keyboards on Windows systems have two keys bearing the label, 'Enter'. The Tk system generates the events, _<KeyPress-Return>_ and _<KeyRelease-Return>_ for both of them; the two keys are indistinguishable. While this behavior is in keeping with the "Microsoft Windows User Experience Guidelines," which explicitly state that the two keys should command identical functionality, it is inconvenient for developers who wish to port Unix applications that already have different actions bound to the _<KeyPress-Return>_ and _<KeyPress-KP\_Enter>_ events. # Specification The solution that has been chosen supports the greatest possible backward compatibility. What is proposed is that 'tkWinX.c' will examine the _KF\_EXTENDED_ bit in the keyboard state \(passed as _lParam_ to the _GetState_ function\) and map it as modifier 4. \(Modifiers 1 through 3, respectively, refer to the _Num Lock_, _Alt_, and _Scroll Lock_ keys.\) An alias shall be added so that _Extended_ may be used in place of _Mod4_. This change has little if any impact on existing Windows code, since modifier 4 is not generated on Windows today. A binding to _<Return>_ will continue to fire for the numeric _Enter_ key, unless there is also a binding to _<Extended-Return>_ which will then take precedence. Existing Unix code that binds _<Return>_ and _<KP\_Enter>_ to identical functionality \(and does not bind _<Mod4-Return>_\) will also not need to change. Again, the existing _<Return>_ binding will fire for the _Enter_ keys on both the main keyboard and the numeric pad. Unix code that has distinct bindings for _<Return>_ and _<KP\_Enter>_ does not function correctly on Windows today - and cannot be made to do so without changing its specification. To port such code to Windows once this change is in place, a developer will have to add bindings to _<Extended-Return>_ that mirror those for _<KP\_Enter>_. Once the developer has done this, the application will distinguish the two keys and fire the appropriate binding for each. Although the immediate purpose of the change is to deal with the numeric _Enter_ key, the effect of the change will be to deal with the rest of the numeric pad the same way; rather than generating events such as _<KeyPress-KP\_0>_ or _<Keypress-KP\_Multiply>_, the system will generate events representing the corresponding keys on the main keyboard, with modifier 4 set to distinguish them. These events are less likely to need to be rebound, since they correspond to printing characters and seldom if ever have different bindings between the numeric pad and the main keyboard. # Reference Implementation The changes require to implement an earlier version of this proposal can be obtained from SourceForge as Tk Patch \#797404. # Summary of Discussion This change has been discussed extensively on the tcl-core mailing list \(<http://aspn.activestate.com/ASPN/Mail/Message/tcl-core/1791694> and several following threads\) and the comp.lang.tcl newsgroup <http://groups.google.com/[email protected]> . The chief proposed alternative to the use of modifier 4 was to modify _tkWinX.c_ so that the _Enter_ key on the numeric pad would generate the same _<KP\_Enter>_ event that it does on Unix. The drawback to this proposal, making it unacceptable to the authors of this TIP, is that existing user code on Windows that establishes bindings to _<Return>_ but not _<KP\_Enter>_ would no longer recognize the numeric _Enter_ key. This problem was seen as a far greater drawback than the need for those porting Unix applications \(and wishing to continue to operate inconsistently with the Microsoft guidelines\) to add an additional binding, particularly in light of the fact that those applications today can't implement the desired functionality on Windows at all. One proposed workaround was to have a default _all_ binding for _<KP\_\*>_ events on Windows fire the corresponding binding for a non-_KP_ keysym. Unfortunately, this solution introduces even worse surprising behavior. A conventional binding to the KP\_\* keysym will have to include a **break** or **return -code break** in order to avoid having this _all_ binding fire - and making it appear as if both keys had been pressed or released. The open issue of what to do about the problem on the Macintosh platform remains. The authors of this TIP are too ignorant of Macintosh programming to address it. This proposal has engendered a fair amount of controversy, as may be seen in the two threads of messages beginning from <http://aspn.activestate.com/ASPN/Mail/Message/1811543> and <http://aspn.activestate.com/ASPN/Mail/Message/1820298> . More recent additional discussion is archived at <http://aspn.activestate.com/ASPN/Mail/Message/2032516> . Vince Darley summarizes it: For example, there is Benny's suggestion to your _all_ counterexample that the counterexample really contains a bug, since any key-binding ought to have **;break** to prevent exactly that problem. Do we guarantee backwards compatibility even with buggy code? Second there is the suggestion that if you really don't want the _all_ binding to fire if another binding has triggered, you could actually check for that manually \(scan the bindtags list, etc\). This would reduce the backwards incompatibility of an overall cleaner solution to effectively nothing. Third, the TIP contains no mention of what the result of this TIP is on the x-platform Tk developer. That they must now have this: bind ... <Return> "pressReturn" bind ... <KP_Enter> "pressEnter" ; # only useful on Unix bind ... <Extended-Return> "pressEnter" ; # only useful on Windows i.e. rather than making their life easier, it has been made more complex! \(In fact the TIP as a whole seems to have a bias against anyone even considering writing the same application on multiple platforms, which seems v. odd for Tk\) # Copyright Copyright © 2003, 2004 by Kevin B. Kenny. All rights reserved. Permission to use this document in accordance with the terms of Open Publication License <http://www.opencontent.org/openpub/> is herewith granted. |
Name change from tip/159.tip to tip/159.md.
|
| < | < | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 159: Extending Tk 'wm' Command to Support Coloured Icons Author: Georgios Petasis <[email protected]> State: Final Type: Project Vote: Done Tcl-Version: 8.5 Created: 01-Oct-2003 Post-History: ----- # Abstract Currently, Tk lacks a mechanism for allowing scripts to place colour icons in the window manager decorations of a toplevel window. Tk supports only the placement of monochrome bitmaps through the _wm iconbitmap_ and _wm iconmask_ commands. This TIP proposes an extension of the _wm_ command with the _iconphoto_ subcommand, which will pass a set of photo images as possible window manager icons. # Rationale Almost all modern window managers or desktop environments offer support for using colour icons in toplevel window decorations. Tk has made some steps in this direction by allowing _wm iconbitmap_ command to also accept a Windows icon file, to be used as an icon for a toplevel under windows. This solution is quite incomplete, and of course works only under windows. No support for colour icons under Unix is currently offered and I \(think\) the same is also true for Mac OS. This TIP proposes the introduction of a new subcommand to the _wm_ command, the _iconphoto_ subcommand. \(_iconimage_ was an alternative that I rejected because bitmaps are also considered images by Tk\). This subcommand will accept a Tk window name and a set of photo image names. These images will then passed to the window manager as possible window icons. The _wm iconphoto_ subcommand will be available under all platforms. However, at this stage of development I will focus mainly on Unix: I don't know anything about Mac OS \(so others must help in this direction\) and support for windows already exists. The final goal will be to support at least windows and Unix. There is currently a patch that implements the Unix port of _wm iconphoto_. Currently, two different approaches are used by Unix applications to specify colour icons. The first approach uses the same mechanism as _wm iconbitmap_ to pass the icon: instead of passing a monochrome pixmap \(that is a bitmap\), they pass a colour pixmap with 3 planes \(no transparency\). This approach works with many modern window managers \(including the ones used by KDE and GNOME\). However, as Joe English noted this approach violates the ICCCM, despite the fact that it is used by some applications \(i.e. gvim\). The second approach \(again pointed by Joe English\) is the one proposed by freedesktop.org: The application defines a window property that holds a special encoding of the colour icons. I don't know exactly how many window managers follow this proposal, but the window managers in two popular desktops \(KDE and GNOME\) support it. My proposal is of course to follow the second approach, as it does not violate the ICCCM. The window property that should be defined is "\_NET\_WM\_ICON". From the specifications <http://www.freedesktop.org/> : > \_NET\_WM\_ICON > \_NET\_WM\_ICON CARDINAL[][2+n]/32 > This is an array of possible icons for the client. This specification does not stipulate what size these icons should be, but individual desktop environments or toolkits may do so. The Window Manager MAY scale any of these icons to an appropriate size. > This is an array of 32bit packed CARDINAL ARGB with high byte being A, low byte being B. The first two cardinals are width, height. Data is in rows, left to right and top to bottom. > Currently both KDE and GNOME window managers scale the provided icons to proper sizes. # Specification This document proposes the following changes to the Tk core: 1. The addition of a new subcommand \(_iconphoto_\) to the _wm_ command. This subcommand will accept the following arguments: > window: the name of a Tk toplevel window. > photo\_image ?photo\_image2 ...?: a set of Tk photo image names, that will be send to the window manager as potential icons. Currently, no other facilities are planned \(like for example getting back the image names that are currently used as icons\). Also, no facilities are provided to request the window manager what icon sizes are preferred, although Xlib offers a relevant function. # Reference Implementation A reference implementation \(initially for just Unix\) is available <http://sf.net/tracker/?func=detail&aid=815751&group_id=12997&atid=312997> . Note that also I have a reference implementation of the first approach \(passing a colour pixmap instead of a bitmap\), in case we decide to follow this approach \(or both simultaneously :-\) \). # Notes I don't know if I have handled the assignment of the four bytes inside the long correctly. Currently the code works fine under Linux. It would be great if somebody could re-write the assignment to use bit-shift operations :-\) # Copyright This document has been placed in the public domain. |
Name change from tip/16.tip to tip/16.md.
|
| < | < | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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 | # TIP 16: Tcl Functional Areas for Maintainer Assignments Author: Don Porter <[email protected]> Author: Daniel Steffen <[email protected]> State: Accepted Type: Process Vote: Done Created: 21-Nov-2000 Post-History: ----- # Abstract This document proposes a division of Tcl's source code into functional areas so that each area may be assigned to one or more maintainers. # Background TCT procedures \(see [[0]](0.md)\) call for each _maintainer_ to be responsible for a portion of Tcl's source code. Certain portions of Tcl's source code are naturally associated with certain other portions. \(For example, the implementation of a command is intimately related to the documentation for that command.\) Establishing a _natural_ division of Tcl's source code into units needing maintainers is a useful preliminary effort toward a public call for volunteer maintainers. See [[24]](24.md) for the mapping of these functional areas to maintainers. # Rationale When someone reports a bug, or offers a patch, he will want to be able to determine what maintainers have oversight over his report. This implies that we seek a simple mapping from something he knows about his bug or patch to the set of maintainers. For a patch, the submitter certainly knows what file\(s\) she is patching. For a bug report, the reporter is likely to know what command or C function he believes to be buggy. Fortunately, every C function or Tcl command \(combined with the platform\) can be associated with exactly one source code file, the file providing the definition of the C function, or the command procedure of the Tcl command. Thus, a mapping from source code file to maintainer is sufficient to complete the determination. The source code file should not be the largest unit, however. Certain sets of files should each be gathered into a larger unit, all files in that unit with the same maintainer\(s\). Tcl's man pages already gather related routines and commands into one page of documentation. Using the modules implied by the man pages, and by the location of routines in particular source code files, a _natural_ division of Tcl into minimal maintainer units follows in the Proposal section below. It may be that some of these minimal units can be joined together into still larger related units. That is not necessary, though. We can just have the same maintainer\(s\) assigned to all the related minimal units. # Functional Areas Tcl shall be divided into the following functional units, each to be assigned one or more maintainers: ## Events 1. **Notifier** - doc/CrtFileHdlr.3, doc/DoOneEvent.3, doc/Notifier.3, doc/Sleep.3, generic/tclNotify.c, macosx/tclMacOSXNotify.c, tests/notify.test, tests/unixNotfy.test, tests/winNotify.test, unix/tclUnixNotfy.c, unix/tclUnixEvent.c, win/tclWinNotify.c 2. **Event Loops** - doc/bgerror.n, doc/update.n, doc/vwait.n, doc/BackgdErr.3, doc/Exit.3, generic/tclEvent.c, tests/event.test 3. **Timer Events** - doc/after.n, doc/CrtTimerHdlr.3, doc/DoWhenIdle.3, generic/tclTimer.c, tests/timer.test 4. **Asynchronous Events** - doc/Async.3, generic/tclAsync.c, tests/async.test 5. **Xt Based Notifier** - unix/tclXtNotify.c, unix/tclXtTest.c 6. **Time Measurement** - compat/gettod.c, compat/strftime.c, doc/clock.n, generic/tclClock.c, generic/tclGetDate.y, library/tzdata/\*, tests/clock.test, tests/winTime.test, tools/loadICU.tcl, tools/makeTestCases.tcl, tools/tclZIC.tcl, unix/tclUnixTime.c, win/tclWinTime.c ## Variables 7. **Variable Commands and Interfaces** - doc/append.n, doc/array.n, doc/global.n, doc/lappend.n, doc/lset.n, doc/set.n, doc/unset.n, doc/upvar.n, doc/variable.n, doc/SetVar.3, doc/UpVar.3, generic/tclVar.c, tests/append.test, tests/lset.test, tests/set.test, tests/set-old.test, tests/upvar.test, tests/var.test 8. **Environment Variables** - doc/Environment.3, generic/tclEnv.c, tests/env.test 9. **Linked C Variables** - doc/LinkVar.3, generic/tclLink.c, tests/link.test ## Objects 10. **Object System and Fundamental Object Types** - doc/Backslash.3, doc/BoolObj.3, doc/Concat.3, doc/DoubleObj.3, doc/DString.3, doc/Encoding.3, doc/FindExec.3, doc/Hash.3, doc/IntObj.3, doc/Object.3, doc/ObjectType.3, doc/PrintDbl.3, doc/SplitList.3, doc/StringObj.3, doc/StrMatch.3, generic/tclEncoding.c, generic/tclHash.c, generic/tclObj.c, generic/tclStringObj.c, generic/tclUtil.c, library/encoding/\*.enc, tools/encoding/\*, tests/dstring.test, tests/encoding.test, tests/stringObj.test, tests/obj.test, tests/util.test 11. **Conversions From String** - doc/GetInt.3, generic/tclGet.c, tests/get.test 12. **bytearray Object Type** - doc/binary.n, doc/ByteArrObj.3, generic/tclBinary.c, tests/binary.test 13. **index Object Type** - doc/GetIndex.3, doc/WrongNumArgs.3, generic/tclIndexObj.c, tests/indexObj.test 14. **list Object Type** - doc/ListObj.3, generic/tclListObj.c, tests/listObj.test 15. **dict Object Type** - doc/DictObj.3, doc/dict.n, generic/tclDictObj.c, tests/dict.test ## Fundamental Built-in Commands 16. **A - H** - doc/break.n, doc/case.n, doc/catch.n, doc/cd.n, doc/concat.n, doc/continue.n, doc/encoding.n, doc/error.n, |
︙ | ︙ | |||
218 219 220 221 222 223 224 | tests/concat.test, tests/error.test, tests/eval.test, tests/foreach.test, tests/format.test, tests/for-old.test | | | 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 | tests/concat.test, tests/error.test, tests/eval.test, tests/foreach.test, tests/format.test, tests/for-old.test 17. **I - L** - doc/if.n, doc/incr.n, doc/info.n, doc/join.n, doc/lindex.n, doc/linsert.n, doc/list.n, doc/llength.n, |
︙ | ︙ | |||
244 245 246 247 248 249 250 | tests/linsert.test, tests/list.test, tests/llength.test, tests/lrange.test, tests/lreplace.test, tests/lsearch.test | | | 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 | tests/linsert.test, tests/list.test, tests/llength.test, tests/lrange.test, tests/lreplace.test, tests/lsearch.test 18. **M - Z** - doc/pwd.n, doc/regexp.n, doc/regsub.n, doc/rename.n, doc/return.n, doc/split.n, doc/string.n, |
︙ | ︙ | |||
268 269 270 271 272 273 274 | tests/rename.test, tests/split.test, tests/string.test, tests/subst.test, tests/switch.test, tests/while-old.test | | | | | | | | | | | | | | | | | | | | | | | | | 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 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 | tests/rename.test, tests/split.test, tests/string.test, tests/subst.test, tests/switch.test, tests/while-old.test 19. **[history]** - doc/history.n, doc/RecEvalObj.3, doc/RecordEval.3, generic/tclHistory.c, library/history.tcl, tests/history.test 20. **[interp]** - doc/interp.n, doc/CrtSlave.3, doc/Limit.3, generic/tclInterp.c, tests/interp.test 21. **[namespace]** - doc/Namespace.3, doc/namespace.n, generic/tclEnsemble.c, generic/tclNamesp.c, generic/tclResolve.c, tests/namespace.test, tests/namespace-old.test 22. **[proc]** - doc/proc.n, doc/uplevel.n, generic/tclProc.c, generic/tclTestProcBodyObj.c, tests/proc.test, tests/proc-old.test, tests/uplevel.test 23. **[scan]** - doc/scan.n, generic/tclScan.c, tests/scan.test ## Channels 24. **Channel Commands** - doc/close.n, doc/eof.n, doc/exec.n, doc/fblocked.n, doc/fconfigure.n, doc/fcopy.n, doc/flush.n, doc/gets.n, doc/open.n, doc/puts.n, doc/read.n, doc/seek.n, doc/socket.n, doc/tell.n, generic/tclIOCmd.c, tests/exec.test, tests/ioCmd.test, tests/remote.tcl, tests/socket.test 25. **Channel System** - doc/chan.n, doc/fileevent.n, doc/ChnlStack.3, doc/CrtChnlHdlr.3, doc/CrtCloseHdlr.3, doc/CrtChannel.3, doc/DetachPids.3, doc/GetStdChan.3, doc/OpenFileChnl.3, doc/StdChannels.3 generic/tclIO.c, generic/tclIO.h, generic/tclPipe.c, tests/chan.test, tests/chanio.test, tests/io.test 26. **Channel Transformations** - generic/tclIOGT.c, generic/tclIORTrans.c, tests/iogt.test, tests/ioTrans.test 27. **Built-in Channel Types** - compat/waitpid.c, doc/GetHostName.3, doc/GetOpnFl.3, doc/OpenTcp.3, doc/pid.n, generic/tclIOSock.c, generic/tclIORChan.c, tests/pid.test, tests/winConsole.test, tests/winPipe.test, unix/tclUnixChan.c, unix/tclUnixPipe.c, unix/tclUnixSock.c, win/cat.c, win/stub16.c, win/tclWinChan.c, win/tclWinConsole.c, win/tclWinPipe.c, win/tclWinSerial.c, win/tclWinSock.c ## Packages 28. **dde Package** - doc/dde.n, library/dde/pkgIndex.tcl, tests/winDde.test win/tclWinDde.c 29. **http Package** - doc/http.n, library/http1.0/http.tcl, library/http1.0/pkgIndex.tcl, library/http/http.tcl, library/http/pkgIndex.tcl, tests/http.test, tests/httpd, tests/httpold.test 30. **msgcat Package** - doc/msgcat.n, library/msgcat/msgcat.tcl, library/msgcat/pkgIndex.tcl, tests/msgcat.test 31. **opt Package** - library/opt/optparse.tcl, library/opt/pkgIndex.tcl, tests/opt.test 32. **registry Package** - doc/registry.n, library/reg/pkgIndex.tcl, win/tclWinReg.c, tests/registry.test 33. **Safe Base** - doc/safe.n, library/safe.tcl, tests/safe.test 34. **tcltest Package** - doc/tcltest.tcl, library/tcltest/tcltest.tcl, library/tcltest/pkgIndex.tcl, tests/tcltest.test 35. **TclOO Package** \(see [[257]](257.md)\) - doc/Class.3, doc/Method.3, doc/class.n, doc/copy.n, doc/define.n, doc/my.n, doc/next.n, doc/object.n, doc/self.n, generic/tclOO.c, generic/tclOO.decls, generic/tclOO.h, generic/tclOOBasic.c, generic/tclOOCall.c, generic/tclOODefineCmds.c, generic/tclOOInfo.c, generic/tclOOInt.h, generic/tclOOMethod.c, tests/oo.test ## File System 36. **Pathname Management** - doc/filename.n, doc/glob.n, doc/FileSystem.3, doc/SplitPath.3, doc/Translate.3, generic/tclFileName.c, tests/fileName.test, tests/unixFile.test, tests/winFile.test, unix/tclUnixFile.c, win/tclWinFile.c 37. **File System Access** - doc/Access.3, doc/GetCwd.3, doc/SetErrno.3, doc/Signal.3, generic/tclFCmd.c, generic/tclIOUtil.c, generic/tclPathObj.c, generic/tclPosixStr.c, macosx/tclMacOSXFCmd.c, tests/fCmd.test, tests/ioUtil.test, tests/unixFCmd.test, tests/winFCmd.test, unix/tclUnixFCmd.c, win/tclWinError.c, win/tclWinFCmd.c ## Initialization, Script Library, and Autoloader 38. doc/library.n, doc/tclvars.n, doc/unknown.n, doc/Init.3, doc/SourceRCFile.3, generic/tclInitScript.h, |
︙ | ︙ | |||
481 482 483 484 485 486 487 | tests/platform.test, tests/security.test, tests/unixInit.test, tests/unknown.test, unix/tclUnixInit.c, win/tclWinInit.c | | | | | | | | | | | | | | | | | | | | | | | 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 | tests/platform.test, tests/security.test, tests/unixInit.test, tests/unknown.test, unix/tclUnixInit.c, win/tclWinInit.c ## Package Support 39. **Package Management** - doc/InitStubs.3, doc/package.n, doc/packagens.n, doc/pkgMkIndex.n, doc/PkgRequire.3, doc/tm.n, generic/tclPkg.c, generic/tclStubLib.c, library/package.tcl, library/tm.tcl, tests/package.test, tests/pkg.test, tests/pkgMkIndex.test, tests/pkg/\*.tcl, tests/tm.test 40. **Dynamic Loading** - compat/dlfcn.h, doc/load.n, doc/StaticPkg.3, generic/tclLoad.c, generic/tclLoadNone.c, library/ldAout.tcl, tests/load.test, unix/dltest/\*, unix/tclLoad\*.c, win/tclWinLoad.c ## Memory Management 41. **Allocation** - doc/memory.n, doc/Alloc.3, doc/TCL\_MEM\_DEBUG.3, doc/DumpActiveMemory.3, generic/tclAlloc.c, generic/tclCkalloc.c, generic/tclThreadAlloc.c 42. **Preservation** - doc/Preserve.3, generic/tclPreserve.c ## Regular Expressions 43. doc/re\_syntax.n, doc/RegExp.3, generic/regc\_color.c, generic/regc\_cvec.c, generic/regc\_lex.c, generic/regc\_locale.c, generic/regc\_nfa.c, generic/regcomp.c, generic/regcustom.h, generic/rege\_dfa.c, generic/regerror.c, generic/regerrs.h, generic/regex.h, generic/regexec.c, generic/regfree.c, generic/regfronts.c, generic/regguts.h, generic/tclRegexp.c, generic/tclRegexp.h, tests/reg.test, tests/regexp.test, tools/uniClass.tcl ## UTF-8 String Management 44. doc/ToUpper.3, doc/UniCharIsAlpha.3, doc/Utf.3, generic/tclUtf.c, tools/uniParse.tcl, tests/utf.test, win/tclWin32Dll.c ## Fundamentals 45. **Parsing and Evaluation** - doc/AddErrInfo.3, doc/AllowExc.3, doc/AssocData.3, doc/CallDel.3, doc/CmdCmplt.3, doc/CrtCommand.3, doc/CrtObjCmd.3, doc/CrtInterp.3, |
︙ | ︙ | |||
595 596 597 598 599 600 601 | tests/expr-old.test, tests/parse.test, tests/parseExpr.test, tests/parseOld.test, tests/result.test, tests/stack.test | | | | 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 | tests/expr-old.test, tests/parse.test, tests/parseExpr.test, tests/parseOld.test, tests/result.test, tests/stack.test 46. **Traces** - doc/TraceVar.3, doc/TraceCmd.3, doc/trace.n, doc/CrtTrace.3, generic/tclTrace.c, tests/trace.test 47. **Bytecode Compiler** - compat/float.h, generic/tclAssembly.c, generic/tclCompCmds.c, generic/tclCompCmdsSZ.c, generic/tclCompExpr.c, generic/tclCompile.c, generic/tclCompile.h, generic/tclExecute.c, |
︙ | ︙ | |||
628 629 630 631 632 633 634 | tests/if.test, tests/incr.test, tests/lsetComp.test, tests/regexpComp.test, tests/stringComp.test, tests/while.test | | | | | | | | | | 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 | tests/if.test, tests/incr.test, tests/lsetComp.test, tests/regexpComp.test, tests/stringComp.test, tests/while.test 48. **Number Handling** \(see [[237]](237.md)\) - generic/tclStrToD.c, generic/tclTomMath.h, generic/tclTomMathInterface.c, generic/tommath.h, libtommath/\* ## Threads 49. doc/Thread.3, generic/tclThread.c, generic/tclThreadJoin.c, generic/tclThreadStorage.c, generic/tclThreadTest.c, tests/thread.test, unix/tclUnixThrd.c, unix/tclUnixThrd.h, win/tclWinThrd.c, win/tclWinThrd.h ## Embedding Support 50. doc/AppInit.3, doc/Tcl\_Main.3, doc/Panic.3, doc/tclsh.1, generic/tclMain.c, generic/tclPanic.c, tests/main.test, unix/tclAppInit.c, win/tclAppInit.c ## Release Engineering 51. **Release Notes** - README, changes, license.terms, */license.terms, compat/README, generic/README, macosx/README, tests/README, tests/pkg/license.terms, tools/README, unix/README, win/README 52. **Portability Support** - compat/dirent.h, compat/dirent2.h, compat/limits.h, compat/fixstrtod.c, compat/memcmp.c, compat/opendir.c, compat/stdlib.h, compat/string.h, |
︙ | ︙ | |||
699 700 701 702 703 704 705 | generic/tclPort.h, unix/tclMtherr.c, unix/tclUnixPort.h, unix/tclUnixCompat.c, win/tclWinMtherr.c, win/tclWinPort.h | | | 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 | generic/tclPort.h, unix/tclMtherr.c, unix/tclUnixPort.h, unix/tclUnixCompat.c, win/tclWinMtherr.c, win/tclWinPort.h 53. **Configuration and Build Tools** - djgpp/Makefile, macosx/Makefile, macosx/Tcl.pbproj/project.pbxproj, tests/all.tcl, tools/configure.in, tools/eolFix.tcl, tools/genStubs.tcl, tools/index.tcl, |
︙ | ︙ | |||
746 747 748 749 750 751 752 | win/tcl.hpj.in, win/tcl.m4, win/tcl.rc, win/tclConfig.sh.in, win/tclsh.ico, win/tclsh.rc | | | | | | | | | > | 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 | win/tcl.hpj.in, win/tcl.m4, win/tcl.rc, win/tclConfig.sh.in, win/tclsh.ico, win/tclsh.rc 54. **Configuration Reporting** \(see [[59]](59.md)\) - doc/RegConfig.3, generic/tclConfig.c, generic/tclPkgConfig.c, tests/config.test, win/tclWinPkgConfig.c 55. **Other Tools** - tools/checkLibraryDoc.tcl, tools/findBadExternals.tcl, tools/genWinImage.tcl, tools/man2html.tcl, tools/man2html1.tcl, tools/man2html2.tcl, tools/regexpTestLib.tcl 56. **LibTomMath** - libtommath/\* 57. **zlib** \(see [[234]](234.md)\) - doc/zlib.n, doc/TclZlib.3, generic/tclZlib.c, tests/zlib.c # Shared Files The following files are shared by all of Tcl. Any maintainer may modify them as necessary to complete changes they are making to their portion of Tcl. Some of the following files define Tcl's API and should be changed only in accordance with TCT approval. * ChangeLog, ChangeLog.\*, doc/man.macros, generic/tcl.decls, generic/tcl.h, generic/tclInt.decls, generic/tclInt.h, generic/tclTest.c, generic/tclTestObj.c, tests/misc.test, unix/tclUnixTest.c, win/tclWinInt.h, win/tclWinTest.c # Generated Files The following files are generated, so they don't need maintainers. * generic/tclDate.c, generic/tclUniData.c, generic/tclDecls.h, generic/tclIntDecls.h, generic/tclIntPlatDecls.h, generic/tclOODecls.h, generic/tclOOIntDecls.h, generic/tclOOStubInit.c, generic/tclOOStubLib.c, generic/tclPlatDecls.h, generic/tclStubInit.c, generic/tommath.h, library/tclIndex, unix/configure, win/configure # Copyright This document has been placed in the public domain. |
Name change from tip/160.tip to tip/160.md.
|
| < | | | | | | < | | > | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 160: Improvements to Terminal and Serial Channel Handling State: Draft Type: Project Tcl-Version: 8.7 Vote: Pending Post-History: Author: Donal K. Fellows <[email protected]> Created: 17-Oct-2003 ----- # Abstract Terminals and other kinds of serial lines have other capabilities and requirements that are not currently controllable using Tcl. This TIP adds new options to [fconfigure] to allow these advanced capabilities to be supported within Tcl in a straight-forward way. # Serial Line Discard Control Serial lines are much slower devices than virtually anything else on a modern computer, and it is quite possible for them to take a very long time to read data. Often, making sure all the data gets across is important. But this is not universally the case, and sometimes it is more useful to discard the output bound for the serial line that is pending in the operating system's own buffers. This can't be enabled by default in any configuration though, since there is no trivial way to distinguish automatically between terminals that are having debugging information written to them and serial lines that were opened for data manipulation and where closing quickly is desirable \(you can't tell them apart even by device major/minor numbers due to the way that /dev/tty is aliased inside the kernel on many Unixes.\) This was even the subject of a subtle bug \(\#525783\) in [[35]](35.md). But since it is still useful, having it controllable by an explicit option is useful. I propose a new option for serial channels on all platforms: _-closemode_. This will have two legal values: drain: Closing the channel will result in a delay until the entire contents of the OS buffers are written. This is the current default. discard: Closing the channel will result in any data in the OS buffers to be thrown away. This can result in data that is being written by other processes being lost. This option will be supported on all platforms where the underlying serial API is sufficiently capable. Where it is not supported, the option will not be defined on serial channels. # Echo and Cooking Control Terminals have a number of modes of operation. Two of the most useful things that can be set relate to echoing and cooking. Echoing is fairly simple to understand. If a terminal has echoing turned on, every character read is written to the terminal automatically without any action from the program reading from the terminal. Most of the time this is a good thing as people want to see what they have typed, but sometimes it is not so good. Examples include where someone is typing in a password \(when they also want their lines cooked\) and where an application is being controlled by single key-presses \(which is a case where neither echoing or cooking are desirable, with echoing being a problem because the key press is causing a different set of visible changes in the program's output.\) Cooking is also fairly simple. A terminal is producing cooked input when it is working in simply-editable line-at-a-time mode. When the terminal isn't in cooked mode, it delivers raw input directly and immediately to the program. Cooked input is the default and is useful for a lot of purposes, but sometimes \(when the application wants to use single key-presses to control it\) raw input is definitely preferable. Example uses of raw input include text editors \(such as vi or emacs\) or terminal-based menu systems. I propose supporting these operation modes within Tcl through a single new option to the [fconfigure] command \(to definitely be implemented on Unix serial channels - because that is the type of stdin in a normal interactive session - and suitably on other platforms if possible\): _-inputmode_. This will have three legal values: normal: This will turn on both echoing and cooking of input, and can be considered to be the default configuration for all terminals. password: This will turn off echoing but leave cooking turned on. raw: This will turn off both echoing and line-cooking. I'm not aware off-hand of any use-cases for echoed raw mode. While there is theoretically a problem due to cross-talk between channels \(similar to that which was observed with the rationale for the _-closemode_ option\), it is practically unlikely to be one since applications that take parsed input from several serial lines are very rare. Officially, the default value of the _-inputmode_ option will be system- and configuration-dependant, since users can use the _stty_ program to configure their terminals prior to calling Tcl. # Copyright This document has been placed in the public domain. |
Name change from tip/161.tip to tip/161.md.
|
| < | < | | | | | | | > | | | | | | | | | > | 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 | # TIP 161: Change Default for Menu's -tearoff Option to False Author: Mark Roseman <[email protected]> State: Draft Type: Project Vote: Pending Created: 19-Oct-2003 Post-History: Tcl-Version: 9.0 ----- # Abstract This TIP proposes changing the default value of the _-tearoff_ option on menu widgets to false, from its current setting of true. # Rationale The default presence of tearoffs for Tk's menus originated with the Motif look & feel, which was the platform standard used for earlier Unix-only versions of Tk. In more modern user interface toolkits on Unix, as well as Macintosh and Windows, menus do not normally have tearoffs associated with them. For applications today, menus without tearoffs are the standard, with tearoff menus being the exception. While turning off the tearoff on menus can be accomplished either with a configuration option on the particular menu, or a global option setting, this can be a source of confusion for the new Tk developer, and too easily forgotten by other developers. Forcing developers to take extra action to achieve "standard" user interface behavior is contrary to Tk's philosophy. # Proposed Change Implementation of this TIP requires only changing a single default in each of the platform specific _tk\*Default.h_ files, and updating the documentation and test cases. # Compatibility Unfortunately, entries in menus are often accessed by index within scripts, and the presence or absence of tearoff affects this index. Therefore, changing the default setting of this option will affect a large number of scripts. Though fixing these scripts will be straightforward \(either through adjusting access to individual menus, or using the option database to turn the tearoff option back on\), because of the incompatibility this TIP is proposed for 9.0 rather than 8.x. # Copyright This document has been placed in the public domain. |
Name change from tip/162.tip to tip/162.md.
|
| < | < | | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 162: IPv6 Sockets for Tcl Author: Rafael MartÃnez Torres <[email protected]> Author: Donal K. Fellows <[email protected]> Author: Reinhard Max <[email protected]> State: Final Type: Project Vote: Done Created: 23-Oct-2003 Post-History: Tcl-Version: 8.6 ----- # Abstract This TIP is about allowing Tcl to use IPv6 sockets in virtually the same way that you would use the current \(IPv4\) sockets. # Rationale IPv6 is the next generation of the IP protocol that underlies Internet sockets. IPv6 advantages include a wider address space \(128 bits instead current 32 bits\), improved mobility, mandatory security at IP layer \(IPsec...\), etc. Tcl should allow the programmers try both protocols at their networking programs without too much effort \(dependant on underlying operating system support, of course\), just accepting the literal address \(192.0.2.42, 2001:DB8::baad:f00d\) or the DNS names \(www.example.com\). # Proposed Change The interpreter should understand: socket 192.0.2.42 http socket 2001:DB8::baad:f00d echo socket -server accept 9999 socket ipv6.example.com 8080 Where a hostname resolves to multiple addresses in multiple families, the addresses are tried one by one as returned by the the resolver library until a connection can be established. The order depends on the resolver library and its configuration; it is deliberately not touched by Tcl, so that local preferences are automatically respected by Tcl programs. For sockets that actually use IPv6 the output of **fconfigure** needs to be changed to reflect the fact: Client sockets: % fconfigure sock5 -peername 2001:DB8::baad:f00d ipv6.example.com 7 % fconfigure sock5 -sockname 2001:DB8::dead:beef 2001:DB8::dead:beef 49198 Server sockets: % socket -server accept 0 sock3 % fconfigure sock3 -sockname 0.0.0.0 0.0.0.0 49198 :: :: 49198 The **-sockname** and **-peername** options are the affected ones; for client sockets they can indicate addresses in the IPv6 or IPv4 namespaces, and for server sockets the **-sockname** option will list all the addresses bound \(2 in the above example\), three elements each. To maximize backward compatibility, the IPv4 address \(if bound\) will always be listed first. \(Client sockets will always only list a single address as they will always be connected by a definite protocol.\) # Reference Implementation A development branch has been opened up; see <http://wiki.tcl.tk/25947> for details. An older patch is available for UNIX platforms <http://www.ngn.euro6ix.org/IPv6/tcl> . # Copyright This document has been placed in the public domain. |
Name change from tip/163.tip to tip/163.md.
|
| < | < | | | | | | | > | | | | | | | | | | | | | | | > | 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 | # TIP 163: A [dict merge] Subcommand Author: Joe English <[email protected]> State: Final Type: Project Tcl-Version: 8.5 Vote: Done Created: 14-Nov-2003 Post-History: ----- # Abstract This TIP proposes a new [dict] subcommand which is used to combine multiple dictionaries. # Specification dict merge ''dictVal1'' ''dictVal2'' ''...'' ''dictValN'' Returns a new dictionary containing all the key/value pairs in _dictVal1_ through _dictValN_. In the case of duplicate keys, values from later arguments override those from earlier ones. # Implementation See SF Patch \#745851 <http://sourceforge.net/support/tracker.php?aid=745851> # Examples See the EXAMPLES section of return\(n\), which currently reads: set options [eval [list dict create -level 1] $args] This could be replaced with set options [dict merge {-level 1} $args] # Notes This feature was suggested during the discussion of [[111]](111.md), but since the vote was already in progress it was not considered at that time. # Copyright This document has been placed in the public domain. |
Name change from tip/164.tip to tip/164.md.
|
| < | < | | | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 164: Add Rotate Subcommand to the Canvas Widget Author: Arjen Markus <[email protected]> Author: Dimitrios Zachariadis <[email protected]> Author: Donal K. Fellows <[email protected]> State: Draft Type: Project Vote: Pending Created: 17-Nov-2003 Post-History: Keywords: Tk,canvas Tcl-Version: 8.7 ----- # Abstract This TIP proposes to add a _rotate_ subcommand to the canvas widget to facilitate rotating items in very much the same way as is now possible with scaling and moving. # Rationale The canvas currently allows a programmer to scale and move items, but the third common affine transformation, rotation, is not supported. This can in itself be simulated by a script \(simply get the coordinates of all items involved, transform them and set the new coordinates\), but if you have several hundreds or even thousands of items this gets very slow. Rotation is easy for polygons and lines: simply transform the coordinates. For circles and circular arcs new bounding boxes must be calculated and in addition for arcs the starting angle must be changed. Implementing rotation should consider what to do with items that can not \(easily\) be rotated: text items, rectangles, non-circular ovals and arcs, widgets and images. Currently, text can not be drawn at an arbitrary angle, so I propose to only transform the coordinates at which the text is "anchored". A similar strategy can be used for widgets and images. For rectangles and general ovals and arcs there are two choices: * Transforming the item into a polygon would solve the definition problem \(these items are defined by a bounding box and the orientation is implicitly assumed\), but might break scripts that look for a particular type of item. * Therefore we will simply calculate a new bounding box and _ignore changes in orientation_. # Proposal Canvases will have a new subcommand, **rotate**, which will rotate the coordinates of chosen items by a specified angle about a specified point. > _canvas_ **rotate** _itemOrTag_ _x_ _y_ _angle_ Note that most of the arguments are very similar to the canvas's **scale** subcommand. _Angle_ is measured in degrees, with positive values indicating anti-clockwise rotation. ## Canvas Item C API Alterations [These are required for this TIP, but are not yet done.] # Reference Implementation A reference implementation does _not_ yet exist. # Future Work Should we also consider the possibility of reflections in a line? Should we also consider more general linear transformations \(to be specified via a 2x2 matrix\)? What about full affine transformations \(i.e. with the translation components\)? If we implement these from the start, we need to do only a little more work. # Comments It might be useful to utilize the -anchor Tk option in all canvas items and add a new "-anchoroffset $x,$y" option, where $x $y be canvas distances relevant to the anchor position. Once defined, or with their default values, the -anchor and -anchoroffset values combined will provide the item's center, for placement and rotation purposes. Item sets, constituting symbols, can then be manipulated easily. It could probably be beneficial to add an -angle option \(and an accomplanying -angleunit one\), to persist a rotation angle in the configuration database. The presence of an angle value other than zero would help negate rotation, thus re-instating the item to its initial orientation. # Copyright This document is placed in the public domain. |
Name change from tip/165.tip to tip/165.md.
|
| < | < | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 165: A User-Data Field for Virtual Events Author: Donal K. Fellows <[email protected]> State: Final Type: Project Vote: Done Created: 17-Nov-2003 Post-History: Keywords: Tk,substitution Tcl-Version: 8.5 ----- # Abstract This TIP proposes adding to virtual events a new field that is not interpreted by Tk. This will make it far easier for user-code to pass information between creators and consumers of events instead of forcing the use of fragile global variables for this purpose. # Rationale Virtual events are a powerful mechanism in Tk for representing window-related occurrences which are not part of the underlying window system's basic event model. Examples of these higher-level events include <<MenuSelect>> and <<ListboxSelect>>, both of which may represent either particular key actions or particular mouse movements/clicks, but neither of which has deep significance to the windowing system. They are very important to the application though! There is a problem with virtual events though, and that is that they do not provide a way of passing some kind of event-specific information via the event. This means, among other things, that neither of the events mentioned above can actually say what it was that was selected, despite the fact that that would be a natural piece of information to include. Other potential uses include in a drag-and-drop system, where the information passed might be the data being dropped, and perhaps even inside Tk itself where refactoring many widgets \(e.g. the spinbox or the scrollbar\) to use virtual events for their semantic events would allow for programmers to track what is going on more easily, a refactoring which would require extra information describing which subcomponent of those widgets is being activated. \(Actually doing such a refactoring is outside the scope of this TIP though.\) # Specification To make this happen, an extra field is required in the XVirtualEvent defined in _generic/tk.h_, which will be placed at the end of the structure and which will be declared like this \(in keeping with the field naming scheme in the rest of that structure\): Tcl_Obj *user_data; This field will normally be NULL, but if not it must be a pointer to a _Tcl\_Obj_ structure with a non-zero reference count. \(This will still leave the XVirtualEvent structure smaller than an XCrossingEvent so no change to core structure sizes will be seen.\) Once the event has had all its binding callbacks called on it, the reference count of the user\_data field will be decremented once \(if it is non-NULL, of course.\) It will be up to the caller of _Tk\_HandleEvent\(\)_ or _Tk\_QueueWindowEvent\(\)_ \(depending on whether the event is being handled synchronously or asynchronously, respectively\) to increment the reference count. The contents of that field will be substituted in binding scripts using the **%d** substitution \("d" for "data"\), with a NULL being treated like an empty string. Empty strings \(and NULLs\) will be substituted as \{\}, similarly to the _%A_ substitution when a key press does not have a character associated with it. Generation of a virtual event with a non-NULL _user\_data_ field will be done using a new event-field option to **event generate**: **-data**. The value passed to that option will be the object to place inside the _user\_data_ field. # Reference Implementation <http://sf.net/tracker/?func=detail&aid=1008975&group\_id=12997&atid=312997> # Copyright This document is placed in the public domain. |
Name change from tip/166.tip to tip/166.md.
|
| < | < | | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | < > | | | | | | | | | | > | 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 | # TIP 166: Reading and Writing the Photo Image Alpha Channel Author: Donal K. Fellows <[email protected]> Author: Simon Bachmann <[email protected]> State: Draft Type: Project Vote: Pending Created: 19-Nov-2003 Post-History: Keywords: Tk,image get,image put Tcl-Version: 8.7 ----- # Abstract This TIP describes how to update the **image get** and **image put** subcommands so as to allow script-level access to the full alpha channel information that has been present in the photo image data model since Tk 8.3. # Rationale Alpha channels. We've had them in Tk's photo image data model \(which is currently 8-bits-per-channel RGBA\) for quite some time now. We can copy the alpha data around inside the image. We now display them correctly on deep-enough displays \(many thanks to the people who have worked on that!\) But can we write alpha data into an image? No. Not unless you have an image format handler that produces alpha data installed \(e.g. the PNG from tkimg.\) I think we should fix this so that people can read and write the full alpha data from scripts. # Proposal I propose to update the _photoImageInstance_ **get** subcommand so that it takes an extra option **-withalpha** \(to be placed after the coordinates\). If that option is specified, the subcommand will return four values instead of three, with the fourth being the contents of the alpha channel for the pixel. Without this new option, the subcommand will return three values as before. I also propose to update the _photoImageInstance_ **put** subcommand so that alpha channel information may be specified in the following ways when using the list-of-lists-of-pixel-data format \(the image-format format will be up to the particular image format code, as always.\) * If a pixel is specified as being the empty string, that pixel will be set to be completely transparent. This parallels the interpretation of the empty string as transparency elsewhere within the core \(notably in [canvas] items.\) * Any standard Tk colour format \(those accepted by **Tk\_GetColor\(\)** - e.g. _bisque2_ or _\#abcdef_\) may have the following suffix added - **@A** - where A is a fractional alpha value in the range 0.0 to 1.0 \(which values correspond to fully transparent and fully opaque respectively.\) * Any standard Tk colour format which does not have a **@A** suffix may have a **\#XX** suffix, where XX is a pair of hex digits that specify an integer alpha value in the range 0 \(fully transparent\) to 255 \(fully opaque\). * Any standard Tk colour format which does not have a **@A** suffix nor a **\#XX** suffix may have a **\#X** suffix, where X is a single hex digit that specifies an integer alpha value in the range 0 \(fully transparent\) to 255 \(fully opaque\). This is expanded in range from 4 bits wide to 8 bits wide by multiplication by 0x11. * All pixel colours that have neither of the foregoing suffixes are to be interpreted as being fully opaque, which is the current situation anyway. * An additional pixel format is to be supported, consisting of a Tcl list of three or four integers in the range 0 to 255, being the value of the red channel, green channel, blue channel and alpha channel respectively in that order. An absent alpha channel is to be interpreted as full opacity. * Two additional pixel formats are to be supported, consisting of a **\#** followed by exactly four or eight hexadecimal digits. When four digits are present, they will be interpreted as containing data for the _RGBA_ channels \(in that order\), and each digit will be expanded internally to 8-bits wide by multiplication by 0x11. When eight digits are present, they will be interpreted as containing data for the _RGBA_ channels \(in that order\) with two digits for each channel. It should also be possible to include alpha information in the data retrieved with the _photoImageInstance_ **data** subcommand. For this, I propose to make the list-of-lists-of-pixel-data format a regular photo image format \(like PNG, GIF, PPM, etc.\) with the name **default**. This format will have no file read/write capabilities. As before, the list-of-lists format will be the default choice for _photoImageInstance_ **data**, and the last one to be tried for _photoImageInstance_ **put**. The main benefit of this change is that it will be possible to request the **default** format explicitly with the **-format** option and - most important - to pass suboptions to the format handler. The **default** image data format shall accept the suboption **-colorformat** _type_ which specifies the format to be used to encode the color and alpha data for each pixel. Accepted values shall be **rgb** for the \#RRGGBB format \(the current format and default for the suboption\), **rgba** for the \#RRGGBBAA format, and **list** for the list format with four elements. This change will have two side effects: * The **-data** option to photo images will accept image data in the list-of-lists form as well. Currently only data in one of the registered file formats is accepted. * The underlying implementation will become simpler and cleaner. Finally, the _photoImageInstance_ **transparency** command's subcommands will be updated in the following way: * The **get** subcommand will be modified to take an extra option, **-alpha** \(to be placed after the coordinates\), that modifies the result to be the integral alpha value \(in the range 0 to 255\) for the specified pixel. Without the option, the result shall continue to be a boolean that is true exactly when the pixel is wholly transparent. * The **set** subcommand will be modified to take an extra option, **-alpha** \(to be placed after the new value\), that modifies the interpretation of the new value so that it is the integral alpha value to be set for the pixel. Without the option, the value will be interpreted as a boolean as before. # Examples Create a small image with a black border and a partially-transparent red area in the center. image create photo transExample transExample put black -to 0 0 10 10 transExample put [email protected] -to 2 2 8 8 Retrieve the alpha value of a pixel near the middle of the image created previously. set aVal [transExample transparency get 5 5 -alpha] Create a green box with a simple shadow effect image create photo foo # Make a simple graduated fill varying in alpha for the shadow for {set i 14} {$i>0} {incr i -1} { set i2 [expr {$i+30}] foo put [format black#%x [expr {15-$i}]] -to $i $i $i2 $i2 } # Put a solid green rectangle on top foo put #080 -to 0 0 30 30 Retrieve image data with alpha information in the list-of-lists form and create a new image with it. image create photo bar -file imageWithTransparency.png set imageData [bar data -format {default -colorformat rgba} # Inspect / modify / save data image create photo baz -data $imageData # Reference Implementation Branch tip-166 on fossil. # Copyright This document is placed in the public domain. |
Name change from tip/167.tip to tip/167.md.
|
| < | < | | | | | | | > | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 167: Add a New Option for Context Help for Windows Author: Ramon Ribó <[email protected]> State: Draft Type: Project Vote: Pending Created: 19-Nov-2003 Post-History: Tcl-Version: 8.7 ----- # Abstract This TIP proposes adding a new option to **wm attributes** for the Windows version of Tk that offers contextual help in that window. Additionally, a new event type **<Help>** is defined, that will be delivered when the user picks the Help button in the window and picks over a widget. The event will be also hitted when user presses F1 over one window. # Rationale Contextual help is very important in a program to help users to interactively learn to use the software capabilities. Windows offers a powerful mechanism to facilite the implementation of this contextual help but current versions of Tk do not take advantage of this feature. The feature cannot be implemented as an extension as a new event type is needed so as to be informed from the OS that the user has chosen to ask for help over that widget. This contextual help is offered in the following way: when a window is configured to have this option, a small question mark button is displayed in the window title bar near the close button. If users pick that button, a question mark cursor is actived and the user can pick a widget \(or location in a widget.\) The typical program reaction to this is to offer a pop-up window with some short help text or to open the program help in the relevant section. Additionally, the new proposed event **<Help>** can also get information when user presses key F1 over one window. This implementation is proposed for the Windows OS only, though in the future some Window Managers like KDE \(in Linux\) have the same feature and could be also implemented. In any case, this TIP only proposes implementation on Windows. # Specification A new option will be added to **wm attributes** with the following syntax: > **wm attributes** _window_ **-contexthelp** ?_boolean_? If set and if the window is transient, the question mark button will appear in the window title bar. A new event **<Help>** is added to the event list so as a user can do: bind $w <Help> {puts "You pressed widget %W"} This event will hit in two situations: when the user presses the question mark in the title bar of the window and pick a widget; and when user presses the F1 key \(or other platform-defined help key\) over one window \(this latter case only for bindings in the toplevel\). The event will support the usual %W %x %y substitutions and other values. # Reference Implementation <http://sf.net/tracker/?func=detail&atid=312997&aid=845248&group\_id=12997> # Comments It would be preferable to use a virtual event **<<Help>>_ instead of extending the set of X events. \(In particular, adding a new **<Help>** event means there has to be a new **HelpMask** bit flag to select for it, and we're running out of event mask bits\). # Copyright This document has been placed in the public domain. |
Name change from tip/168.tip to tip/168.md.
|
| < | < | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 168: Cubic Bezier Curves on the Canvas Author: Lars Hellström <[email protected]> Type: Project State: Final Tcl-Version: 8.5 Vote: Done Created: 25-Jan-2004 Post-History: ----- # Abstract This document proposes a new **-smooth** method for **line** and **polygon** canvas items that supports cubic Bezier curves and clarifies some of the existing terminology in that area. # Proposal A new method for the **-smooth** canvas item option will be defined. Under this method, the points defining the item will be interpreted as a sequence _knot-point_ _control-point_ _control-point_ _knot-point_ _control-point_ _control-point_ ... of a curve composed of cubic Bezier segments. More precisely, if the list of coordinates is ![List of coordinates](../assets/168ab.png) then the _N_th \(counting from zero\) segment of the curve consists of points whose coordinates _\(x,y\)_ satisfies ![Parametric equations for x and y](../assets/168xy.png) for some value of _t_ between 0 and 1, inclusive. If there are _3N\+1_ points then the above defines an _N_ segment curve. In the case that the number of points is _3N_ or _3N-1_ then they shall still define an _N_ segment curve, where in the first case the first knot of the first segment is reused as the last knot in the last segment, and in the second case the first knot and control point in the first segment are reused as the last control point and knot in the last segment respectively. Straight line segments in the curve can be encoded as a segment where the control points are equal to the neighbouring knot points. While this is not the only way to encode a straight line, it is a case that is recognised and handled more efficiently by code that renders the canvas item. The name of this new method should be "**raw**". The name of the existing **-smooth** method \(as returned by the itemcget widget command\) should be changed from "**bezier**" to "**true**", and the name "**bezier**", while at least in Tcl 8.5 still supported, should be deprecated. # Rationale Cubic Bezier curves, being for example the native curve format in Postscript and its descendants, is probably the most common format for smooth curves in computing today. It is even used internally in Tk; for each segment of a **-smooth 1** curve, rendering starts with the calculation of a cubic Bezier representation of that curve and continues to use only this representation when approximating the smooth curve with straight line segments. Hence it might be claimed that the cubic Bezier curve is the "raw" format of a smooth curve in Tk. No new calculations need to be implemented in the core to implement this TIP, it is merely a matter of combining existing functions in a suitable way and move data around. Therefore it seems a waste to not provide cubic Bezier curves, when they are anyway already half implemented. The reason for the interpretation of a curve with _3N_ points given is that this will cause the curve to be closed. Conversely, omitting the final knot point is sometimes used as a way of encoding the fact that the curve should be closed. This rule will therefore facilitate the use of data where then omitted endpoint convention has been employed. The only reason for the _3N-1_ point rule is that it fits a simple scheme \(when at the end of the list of coordinates, continue from the start\) that supports the _3N_ and _3N\+1_ cases. The reason for deprecating the name "**bezier**" for the traditional smoothing method is that it is at best confusing, and according to many authorities simply wrong. The term "Bezier curve" is very often used as a synonym of "cubic Bezier curve", whence the majority of programmers new to this feature of the canvas widget would probably expect "**-smooth bezier**" to imply the effect of the smoothing option proposed in this document rather than the smoothing via quadratic splines that it currently is. The amount of disappointment that could result from the unpleasant discovery that what one thought was the former is really the latter should not be underestimated. The reason for changing the official name of the traditional smoothing method to "**true**" are \(i\) that it is backwards compatible in the sense that this name works for specifying that smoothing method in all Tk versions and \(ii\) that it is somewhat mnemonic, because it happens to coincide with the format used for curves in _True_Type fonts. # Background The question of what may rightfully be called "**bezier**" is somewhat complicated and deserves expounding upon. It really begins with Bernstein; the _Bernstein degree n form_ of a polynomial f is ![Bernstein degree n form polynomial](../assets/168f.png) One advantage this form has over the standard form is that the coefficients _a\_0, ..., a\_n_ are directly comparable to the function values _f\(0\), f\(1/n\), f\(2/n\), ..., f\(1\)_; the two are generally not equal \(with the exception for the endpoints of the _[0,1]_ interval\), but the function values approximates the sequence of coefficients in various useful ways. \(Bernstein used it to give an elegant proof of the Weierstrass Approximation Theorem.\) A _Bezier curve_ \(or Bernstein-Bezier curve, as it is sometimes called\) of degree _n_ is a parametric curve _P_ defined by a sequence of _n\+1_ points _P\_0, ..., P\_n_ \(known as the _control points_ of the curve\) where each coordinate function is the Bernstein polynomial one gets by taking as _a\_k_ the corresponding coordinate of the point _P\_k_ and parametric time goes from _0_ to _1_; formally ![Bernstein polynomial for points](../assets/168P.png) for _t_ between _0_ and _1_ inclusive. Higher degree Bezier curves are not used much in computer graphics \(probably because the effect on the curve of moving an single control point is often not intuitively clear\) but they do exist and it is not illogical to expect that a $canvas create line $points -smooth bezier should be the degree-[expr {[llength $points]/2 - 1\}] Bezier curve defined by the given points. Another term which often occurs when discussing computer graphic curves is "spline". A _spline_ is a curve that passes through a set of given points \(the _knots_ of the curve\) in a given order, satisfies some smoothness condition, and in some sense is best possible under these conditions. The most common optimality condition is that the curve should be composed from segments that can be parameterized by polynomials of given degree, but there are implicit conditions \(minimizing some suitable measure of curve deformation\) which leads to the same family of curves. The **-smooth 1** curves of the Tk canvas are splines \(of degree _2_\) in this sense, even though the points used for defining them are \(with the exception for endpoints\) not the knots of the spline. \(Rather, the internal knots are the midpoints of the line segments joining two adjacent control point.\) The **raw** curves proposed here are in general _not_ splines \(because they admit discontinuous changes in tangent direction, thus violating the smoothness condition\), but they often serve as an encoding for pre-computed degree 3 splines and this use has lead to a confusion in terminology in this area. It is not uncommon that piecewise cubic Bezier curves in general are referred to as "cubic splines", even though that is a more special concept. It may also be observed that the endpoints of the Bezier segments are usually referred to as _knots_ of the curve, whereas the term "control points" is often reserved for the non-knot control points. This rather harmless convention is for example used above. Incorrect use of the word "spline" should however be avoided. # Alternatives It would be possible to provide the suggested functionality using a compiled extension instead, but that seems a waste since almost all of the functionality is present in the core anyway. It would also be possible to use the semantics of the Tkspline package <http://www.graphviz.org/cgi-bin/man?tkspline> **-smooth** method providing cubic Bezier curves, but that package reverts to using the **-smooth true** method of smoothing if the number of points is not _3N\+1_, which doesn't seem useful and may cause bugs to be less visible. Using the Tkspline syntax \(calling the **-smooth** method "spline"\) should probably be avoided even if the two methods were compatible, since the curves produced in general aren't splines. # Implementation A sample implementation of this proposal \(minus the part about changing the name of the existing **-smooth** method\) exists <http://sf.net/tracker/?func=detail&aid=886240&group_id=12997&atid=312997> . # Copyright This document has been placed in the public domain. |
Name change from tip/169.tip to tip/169.md.
|
| < | < | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 169: Add Peer Text Widgets Author: Brian Griffin <[email protected]> Author: Vince Darley <[email protected]> State: Final Type: Project Vote: Done Created: 28-Jan-2004 Post-History: Tcl-Version: 8.5 ----- # Abstract This TIP proposes adding a method to the text widget that will create peer text widgets, allowing two or more text widgets to share the same text, tags, and marks. # Rationale One of the features offered by many text editors is the ability to split the view of text being edited. Currently editors based on the Tk text widget are required to create multiple widgets, duplicating all insert, delete, etc., operations on both widgets. The current text widget already separates almost all aspects of the data from the widget rendering and it would be a simple task to allow two \(or more\) widgets to share this data. # Proposed Change The primary change is the addition of a 'peer' subcommand to any text widget, as follows: $text peer create ... $text peer names The proposed implementation splits the widget structure into two pieces, sharable data and widget specific rendering parts. The text tree, tags \(including their colours and fonts\), marks, images, and undo stack would be placed in a reference counted, shared section, while the widget configuration options for tkwin, fonts, colors, bindings, etc., would remain with the widget. A method \(peer create\) is added that will create a new widget that will share the data with it's "parent." The shared data also contains a list of peers which is used to propagate widget updates when the data changes. set widget [text .text] set peer [$widget peer create .peer] Once a peer is created it has all the rights and privileges of the creating parent. There is no restriction on the peer's window pathname. The creating parent may also be destroyed without affecting the peer; only when the last window \(peer or parent\) is destroyed will the data be deleted. In keeping with Tcl's introspection nature, a "peer names" method is added that will return a list of peer widgets. This list does not include itself. Lastly, all text widgets take two new configuration options to specify that the peer only shows a subset of the lines from the underling b-tree: set peer [$widget peer create .peer -startline 53 -endline 125] will create a peer which contains lines 53 to 125 of the underlying data store. The default is for a peer to contain the same range of lines as its 'parent', but one can use '-startline \{\} -endline \{\}' to force use of the entire b-tree. Any peer widget can access a list of all _other_ peers, via the 'peer names' command: set peerlist [$widget peer names] This list does not include $widget itself. # Detailed Description All geometry/pixel-height information for peer widgets are calculated separately for each peer. This means each peer can have different height, width, scrollbar state, \(even overall font size\) with no problems. The 'sel', 'insert', 'current' tag/marks are not shared. They are widget specific. Similarly the '-window' attribute of any embedded window is not shared, but widget specific \(i.e. it can be configured separately for each peer\). The '-create' option of an embedded window now supports % substitution of its script to allow multiple peers all to have embedded windows in a relatively easy fashion. '%W' is substituted by the embedding text widget pathname and '%%' by '%'. So, for example, the following test works nicely: test textWind-17.6 {peer widget window configuration} { catch {destroy .t .tt} pack [text .t] .t delete 1.0 end .t insert 1.0 "Some sample text" toplevel .tt pack [.t peer create .tt.t] .t window create 1.2 -create {frame %W.f -width 10 -height 20 -bg blue} update ; update set res [list [.t window configure 1.2 -window] \ [.tt.t window configure 1.2 -window]] destroy .tt .t set res } {{-window {} {} {} .t.f} {-window {} {} {} .tt.t.f}} All top-level text configuration options are widget-specific except those which involve the undo/redo/modified status of the widget, which are shared. # Further changes It has been pointed out that some uses of the 'sel' tag in existing Tk-based editors require an additional tag for use when a given widget does not have the input focus \(a 'background sel' tag\), particularly on Windows/MacOS X where <https://sourceforge.net/tracker/?func=detail&atid=112997&aid=1014213&group_id=12997> applies \(selection is never shown in text widgets which don't have the focus\). Such an approach would not work with peer widgets, because the 'background sel' tag would show up on all peers. This means the cited problem needs to be fixed, and we need programmatic control over the visualization of the "sel" tag in text widgets that don't have the focus. The proposed solution is the addition of a 'inactiveSelectionBackground' option to each text overall widget. This new text widget configuration option can take the \{\} value, in which case the selection is not shown when the widget is not active, or if it takes a value, then that is the colour to use for the inactive selection. This option is peer-widget-specific \(and is effectively implemented by over-riding the 'sel' background colour if the widget doesn't have the focus; a minor modification to the current code on Win/MacOS which ignores 'sel' when the widget doesn't have the focus\). # To Do In the current patch \(and in the original version of this TIP\), bindings are not shared, but remain with the widget. Currently this includes tag bindings, but I think it would be better if tag bindings were shared \(given that tags are shared\). Unless anyone has a use-case showing why they should be independent, I'll update the implementation accordingly. Therefore shared tag bindings should be considered part of this TIP. # Alternatives This does not preclude a future TIP from going further and making the B-tree data structure a fully-fledged Tcl structure \(like an array or a dict or whatever\), of which the text widget is just one example of a client. However, such issues are beyond the scope of this TIP \(except to point out that the implementation is, by necessity, many steps in the same direction\). # Reference Implementation A reference implementation based on Tcl 8.5 is available at: <http://sourceforge.net/tracker/?func=detail&atid=312997&aid=994629&group\_id=12997> This includes new tests and documentation, and an update to one of the Text widget demos to show off the new functionality. Incidentally, this patch also fixes the long-standing problem where renaming the text widget breaks the undo-stack \(which used to record the actual widget name\). # Copyright This document has been placed in the public domain. |
Name change from tip/17.tip to tip/17.md.
|
| < | < | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | < > | | | | < > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | < | > | | < | > | | < > | | < > | | < > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 | # TIP 17: Redo Tcl's filesystem Author: Vince Darley <[email protected]> State: Final Type: Project Vote: Done Created: 17-Nov-2000 Post-History: Tcl-Version: 8.4.0 ----- # Abstract Many of the most exciting recent developments in Tcl have involved putting virtual file systems in a file \(e.g. Prowrap, Freewrap, Wrap, TclKit\) but these have been largely _ad hoc_ hacks of various internal APIs. This TIP seeks to replace this with a common underlying API that will, in addition, make porting of Tcl to new platforms a simpler task as well. # Overview There are two current drawbacks to Tcl's filesystem implementation: * virtual filesystems are not properly supported. * it is all string-based, rather than Tcl\_Obj-based. Prowrap \(<http://sourceforge.net/projects/tclpro\),> Freewrap \(<http://home.nycap.rr.com/dlabelle/freewrap/freewrap.html\),> Wrap \(<http://members1.chello.nl/~j.nijtmans/wrap.html\),> TclKit \(<http://www.equi4.com/jcw/wiki.cgi/19.html\),> ... are all attempts to provide an ability to place Tcl scripts and other data inside a single file \(or just a small number of files\). The best and simplest way to achieve that task \(and many other useful tasks\) is to let Tcl handle the contents of a single 'wrapped document' as if it were a filesystem: the contents may be opened, sourced, stat'd, copied, globbed, etc. Also note that at the European Tcl/Tk meeting, the \(equal\) second-ranked request for Tcl was support for standalone executables \(<http://mini.net/cgi-bin/wikit/837.html\).> This TIP suggests that Tcl's core be modified to allow non-native filesystems to be plugged in to the core, and hence allow _perfect_ virtual filesystems to exist. The implementations provided by all of the above tools are very far from perfect. The most obvious types of virtual filesystem which should be supported are: * wrapped/archived document 'bundles' such as TclKits, .zip files, etc. * remote filesystems \(e.g. an FTP site\). but the main point is that all filesystem access should occur through a hookable interface, so that Tcl neither knows nor cares what type of filesystem it is dealing with. Furthermore this hookable interface should be Tcl\_Obj based, providing a new 'Path' object type, which should be designed with two goals in mind: * allow caching of 'native path representations' \(all native Tclp... filesystem calls involve various Utf->Native conversions\). For example, quick testing for 'file exists' shows that a 20% speed up can be achieved by caching the native representation \(Windows 2000sp1\). * allow virtual filesystems to operate very efficiently - this will probably require caching of the filesystem to use for a particular file. If all of these goals are achieved, Tcl will have a new filesystem which is both more efficient and more powerful than the existing implementation. # Technical discussion 1. Virtual filesystems > An examination of the core shows that a very limited support was added to tclIOUtil.c in June 1998 \(presumably by Scriptics to support prowrap\) so that TclStat, TclAccess and Tcl\_OpenFileChannel commands could be intercepted. \(See <http://cvs.sourceforge.net/cgi-bin/cvsweb.cgi/tcl/generic/tclIOUtil.c?rev=1.2&content-type=text/x-cvsweb-markup&cvsroot=tcl\)> > This TIP seeks to provide a _complete_ implementation of virtual file system support, rather than these piecemeal functions. > Fortunately, since Tcl is already abstracted across three different filesystem types \(through the Tclp...\) functions, it is not that big a task to abstract away to any generic filesystem. > One goal of this TIP is to allow an _extension_ to be written so that one can implement a virtual filesystem entirely in Tcl: i.e. to provide sufficient hooks into Tcl's core so that an extension can capture all filesystem requests and divert them if desired. The goal is not to provide Tcl-level hooks in Tcl's core. Such hooks will only be at the C level, and an extension would be required to expose them to the Tcl level. 2. Objectified filesystem interface. > Every filesystem access in Tcl's core usually involves several calls to 'access', 'stat', etc. > For example 'file atime $path' requires two calls to 'stat' and one call to 'utime', all with the same $path argument. Each of these requires a conversion from the same Utf path to the same native string representation. No caching is performed, so each of these goes through Tcl\_UtfToExternal. Often Tcl code will use the same $path objects for an entire sequence of Tcl 'file' operations. Clearly a representation which cached the native path would speed up all of these operations \(except the first\). > The second reason why objectification is desirable is that in a pluggable-fs environment we must determine, for each file operation, which filesystem to use \(whether native, a mounted .zip file, a remote FTP site, etc.\). If this information can be cached for a particular path, again we will not need to recalculate it at every step. A similar technique to that used by Tcl's bytecode compilation will be used: each cached object will have a "filesystemEpoch" counter, so that we can tell with each access whether the filesystem has been modified \(and we must discard the cached information\). Mounting/unmounting filesystems will obviously modify the filesystemEpoch. > A relatively complete implementation of this TIP, and a sample "vfs" extension now exist, and have been tested through TclKit. On both the "virtual" and "objectification" parts of this tip, the implementation is known to be stable and complete \(at least on Windows\): TclKit can operate through this new vfs implementation without the need to override a single Tcl core command at the script level, and all reasonable filesystem tests \(cmdAH.test, fCmd.test, fileName.test, io.test\) pass in a scripted document. Commands which operate on files \(image, source, etc.\) and extensions like Image, Winico can be made to work in a TclKit automatically! There is still some room for optimisation in some parts of the new objectification code \(which wasn't possible in the old string-based API\). The current implementation has great efficiency gains for vfs's implemented at the script level, since the same Path objects can be passed through the entire process, without an intermediate conversion \(and string duplication which would otherwise be required\). The combination of caching and objectification changes the existing list of steps from Tcl_Obj -> string -> filesystem -> convert-to-native -> native-call > or \(with vfs hooked in\) Tcl_Obj -> string -> vfilesystem -> pick-filesystem -> convert-to-native -> native-call > and Tcl_Obj -> string -> vfilesystem -> pick-filesystem -> Tcl_NewStringObj -> Tcl-vfs-call > to Tcl_Obj -> vfilesystem -> native-call > and Tcl_Obj -> vfilesystem -> Tcl-vfs-call ---- A final side-benefit of this proposal would be that it further modularises the core of Tcl, so that one could, in principle: * remove the native filesystem support entirely from Tcl \(perhaps useful for embedded devices etc\), since there will be a clean layer separating Tcl from its native filesystem functionality. * use Tcl's filesystem for other purposes \(outside of Tcl\). However these final two points are explicitly _not_ the goal of this TIP! I simply want to improve Tcl to add vfs support, and the best way to do that seems \(to me\) to be along the lines of this TIP. # Proposal The changes to Tcl's core for virtual filesystem support are actually very minor. Every occurrence of a Tclp-filesystem call must be replaced by a call to a hookable procedure. The current filesystem structure \(defined in tclInt.h\) and hookable procedure list is as follows \(for documentation on this structure, see Documentation section below\): /* * struct Tcl_Filesystem: * * One such structure exists for each type (kind) of filesystem. * It collects together in one place all the functions that are * part of the specific filesystem. Tcl always accesses the * filesystem through one of these structures. * * Not all entries need be non-NULL; any which are NULL are simply * ignored. However, a complete filesystem should provide all of * these functions. */ typedef struct Tcl_Filesystem { CONST char *typeName; /* The name of the filesystem. */ int structureLength; /* Length of this structure, so future * binary compatibility can be assured. */ Tcl_FilesystemVersion version; /* Version of the filesystem type. */ TclfsPathInFilesystem_ *pathInFilesystemProc; /* Function to check whether a path is in this * filesystem */ TclfsDupInternalRep_ *dupInternalRepProc; /* Function to duplicate internal fs rep */ TclfsFreeInternalRep_ *freeInternalRepProc; /* Function to free internal fs rep */ TclfsInternalToNormalizedProc_ *internalToNormalizedProc_; /* Function to convert internal representation * to a normalized path */ TclfsConvertToInternalProc_ *convertToInternalProc_; /* Function to convert object to an * internal representation */ TclfsStatProc_ *statProc; /* Function to process a 'Tcl_Stat()' call */ TclfsAccessProc_ *accessProc; /* Function to process a 'Tcl_Access()' call */ TclfsOpenFileChannelProc_ *openFileChannelProc; /* Function to process a 'Tcl_OpenFileChannel()' call */ TclfsMatchInDirectoryProc_ *matchInDirectoryProc; /* Function to process a 'Tcl_MatchInDirectory()' */ TclfsGetCwdProc_ *getCwdProc; /* Function to process a 'Tcl_GetCwd()' call */ TclfsChdirProc_ *chdirProc; /* Function to process a 'Tcl_Chdir()' call */ TclfsLstatProc_ *lstatProc; /* Function to process a 'Tcl_Lstat()' call */ TclfsCopyFileProc_ *copyFileProc; /* Function to process a 'Tcl_CopyFile()' call */ TclfsDeleteFileProc_ *deleteFileProc; /* Function to process a 'Tcl_DeleteFile()' call */ TclfsRenameFileProc_ *renameFileProc; /* Function to process a 'Tcl_RenameFile()' call */ TclfsCreateDirectoryProc_ *createDirectoryProc; /* Function to process a 'Tcl_CreateDirectory()' call */ TclfsCopyDirectoryProc_ *copyDirectoryProc; /* Function to process a 'Tcl_CopyDirectory()' call */ TclfsRemoveDirectoryProc_ *removeDirectoryProc; /* Function to process a 'Tcl_RemoveDirectory()' call */ TclfsLoadFileProc_ *loadFileProc; /* Function to process a 'Tcl_LoadFile()' call */ TclfsUnloadFileProc_ *unloadFileProc; /* Function to unload a previously successfully * loaded file */ TclfsReadlinkProc_ *readlinkProc; /* Function to process a 'Tcl_Readlink()' call */ TclfsListVolumesProc_ *listVolumesProc; /* Function to list any filesystem volumes added * by this filesystem */ TclfsFileAttrStringsProc_ *fileAttrStringsProc; /* Function to list all attributes strings which * are valid for this filesystem */ TclfsFileAttrsGetProc_ *fileAttrsGetProc; /* Function to process a 'Tcl_FileAttrsGet()' call */ TclfsFileAttrsSetProc_ *fileAttrsSetProc; /* Function to process a 'Tcl_FileAttrsSet()' call */ TclfsUtimeProc_ *utimeProc; /* Function to process a 'Tcl_Utime()' call */ TclfsNormalizePathProc_ *normalizePathProc; /* Function to normalize a path */ } Tcl_Filesystem; Once that is done, almost no more _changes_ need be made to Tcl's core. We must simply add code \(to tclIOUtil.c and declarations to tclInt.h\) to implement the hookable functions and to provide a simple API by which extensions can hook into the new filesystem support. This gives us the simplest level of vfs. Most remaining changes are objectifying the way Tcl's core uses filesystems. Many of these changes actually simplify the core, for example, we replace: case FILE_COPY: { int result; char **argv; argv = StringifyObjects(objc, objv); result = TclFileCopyCmd(interp, objc, argv); ckfree((char *) argv); return result; } with case FILE_COPY: { return TclFileCopyCmd(interp, objc, objv); } and the Unix versions of stat, access, chdir are as simple as: int TclpObjStat(Tcl_Obj *pathPtr, struct stat *buf) { return stat(Tclfs_GetNativePath(pathPtr), buf); } int TclpObjChdir(Tcl_Obj *pathPtr) { return chdir(Tclfs_GetNativePath(pathPtr)); } int TclpObjAccess(Tcl_Obj *pathPtr, int mode) { return access(Tclfs_GetNativePath(pathPtr)); } There are a few other small changes required, some which are absolutely necessary, and some which make the implementation of a Tcl-level vfs much simpler and more robust: * Cross-filesystem copy and rename operations will fail. A patch was added so that Tcl can fall back on 'open r/open w/fcopy/file mtime' as a copying method for files, and a new function ::tcl::copyDirectory for directories. These techniques are only used if the source/dest are in different filesystems, or if the filesystem Tcl tries to use returns the EXDEV posix result in 'errno'. This is a natural extension of Tcl's current way of falling back from 'rename' to 'copy and delete'. * Add _-tails_ flag to _glob_ \(and internally to _TclGlob_\) to indicate that we only want the tails of the files to be returned. * Add _file normalize path_ subcommand to _file_, which returns an absolute path in which all "..", "." sequences have been removed, and the file is a platform-normalized path \(e.g. the longname is used on windows\). * Modify the TclDoGlob implementation so it handles recursion itself, rather than passing it on to the various TclpMatchFilesTypes functions. This simplifies the platform-specific code, and makes vfs support of _glob_ much more robust, easy, complete, etc. This has the side- benefit that TclpMatchFilesTypes need not operate directly on the interpreter's result. The simpler function with a different signature has been named _TclpMatchInDirectory_. * Modify the implementation of _encoding names_ to use the TCL\_GLOBMODE\_TAILS flag to TclGlob, simplifying that code. * Add an API to tclIO.c to allow us to Unregister a channel _without_ deleting it. We need this to be able to take a channel created in Tcl \(registered and with refcount of 1\) and turn it into a "pristine channel with refcount 0" as returned by Tcl\_OpenFileChannel. This is called _Tcl\_DetachChannel_. * Add a function to tclInt.decls called 'TclpVerifyInitialEncodings' which is required when all of Tcl is packaged in a virtual filesystem \(e.g. TclKit\), since Tcl's very early call to TclpSetInitialEncodings fails to achieve anything useful. * the perfect vfs support can have some weird side-effects. For instance, if I embed all of tcltest and tests/ inside a TclKit, and try to source 'all.tcl', I get errors that each file does not exist. This is because the test code tries to pipe each file in turn to a newly created tcl process \(open "\| tclsh foo.test r"\), but the files don't really exist \(as far as the OS is concerned\). We therefore add an introspection command 'file system $path' which returns a list of two items: the name of the filesystem and the type of the file within that filesystem. For example it might be 'native local', 'native networked', 'vfs ftp', 'vfs zip' etc. * vfs systems on different platforms may require different directory separator characters \(different to the native characters\), especially on MacOS \(in which a valid file might be _HD:Tcl:tcl.zip/lib/tcl8.4/history.tcl_\), and we therefore add 'file separator ?filename?' command to retrieve the correct separator to use. As mentioned above an implementation of all of this now exists. The modified Tcl core passes all Tcl tests, and works with a new version of TclKit \(which can itself pass all reasonable tests when executing the test suite inside a scripted document\). It has been tested with a variety of wrapped demos \(tclhttpd, bwidgets, widgets, alphatk\), and performs very well. The patch is available from the author of this TIP, and a version \(possibly not the most recent\) can be downloaded from: ftp://ftp.ucsd.edu/pub/alpha/tcl/tclobjvfs.diff # Documentation: vfs-aware extensions All calls to filesystem functions in Tcl's core and in extensions should preferably be made through the new API defined in tclInt.decls. All these functions have the prefix 'Tclfs\_'. Of course extensions which call older string-based APIs \(e.g. Tcl\_OpenFileChannel\) will still work, but will not benefit from the efficiency of the cached object representation. Most of these functions are not commonly used by extensions \(e.g. Tclfs\_CopyDirectory\), so only the most common are listed here: Tcl_Channel Tclfs_OpenFileChannel(Tcl_Interp *interp, Tcl_Obj *pathPtr, char *modeString, int permissions) int Tclfs_EvalFile(Tcl_Interp *interp, Tcl_Obj *fileName) int Tclfs_Stat(Tcl_Obj *pathPtr, struct stat *buf) int Tclfs_Access(Tcl_Obj *pathPtr, int mode) These replace the equivalent string-based APIs. int Tclfs_ConvertToPathType(Tcl_Interp *interp, Tcl_Obj *pathPtr) Attempts to convert the given object to a path type. This is a little more than a simple wrapper around _Tcl\_ConvertToType\(interp, pathPtr, &tclFsPathType\)_. If it returns TCL\_ERROR, the object is not a valid path. In this sense it is very similar to Tcl\_TranslateFileName for the existing string-based API. It should be called before attempting to pass an object to any of the other filesystem APIs \(again in much the same way as Tcl\_TranslateFileName was used in the core\). int Tclfs_EqualPaths(Tcl_Obj* firstPtr, Tcl_Obj* secondPtr) Tcl_Obj* Tclfs_SplitPath(Tcl_Obj* pathPtr, int *lenPtr) Tcl_Obj* Tclfs_JoinPath(Tcl_Obj *listObj, int elements) Tcl_Obj* Tclfs_JoinToPath(Tcl_Obj *basePtr, int objc, Tcl_Obj *CONST objv[]) These all manipulate paths. They return Tcl\_Obj\* with refCounts of zero. Tcl_Obj* Tclfs_GetNormalizedPath(Tcl_Interp *interp, Tcl_Obj* pathObjPtr) char* Tclfs_GetTranslatedPath(Tcl_Interp *interp, Tcl_Obj* pathPtr) and finally: char* Tclfs_GetNativePath(Tcl_Obj* pathObjPtr) which is used by native filesystems only, and is a shorthand for getting at the cached native representation for MacOS, Windows or Unix \(as appropriate\). This is always a string based representation, but may really be of type TCHAR\* on Windows, for example. # Documentation: writing a new filesystem The _objPtr->internalRep.otherValuePtr_ field is a pointer to one of these structures, for objects of "path" type. typedef struct FsPath { char *translatedPathPtr; /* Name without any ~user sequences */ Tcl_Obj *normPathPtr; /* Normalized absolute path, without . * or .. sequences, and without ~user * sequences. */ Tcl_Obj *cwdPtr; /* If null, path is absolute, else * this points to the cwd object used * for this path. We have a refCount * on the object. */ ClientData nativePathPtr; /* Native representation of this path, * which is filesystem dependent. */ int filesystemEpoch; /* Used to ensure the path representation * was generated during the correct * filesystem epoch. The epoch changes * when filesystem-mounts are changed. */ struct Tcl_FilesystemRecord *fsRecPtr; /* Pointer to the filesystem record * entry to use for this path. */ } FsPath; Path to filesystem mapping: int TclfsPathInFilesystem_ (Tcl_Obj *pathPtr, ClientData *clientDataPtr) Is the given path in this filesystem? This function should return either -1, or it should return TCL\_OK. If it returns TCL\_OK, it may wish to set the clientData parameter to point to a filesystem specific representation of the path. \(The native filesystem actually postpones the calculation of the native representation until it is requested, but TclKit's vfs immediately allocates a structure containing an int and Tcl\_Obj\* which it uses as an internal representation\). Internal representation manipulation: void TclfsFreeInternalRep_ (ClientData clientData) ClientData TclfsDupInternalRep_ (ClientData clientData) These two are called to duplicate and free the clientData field of the FsPath structure. If they are NULL, they are ignored \(and on duplication, the new object's clientData field is set to NULL\). Path normalization: int TclfsNormalizePathProc_ (Tcl_Interp *interp, Tcl_Obj *pathPtr, int nextCheckpoint) This function should check the string representation of pathPtr, starting at character index 'nextCheckpoint', and convert it from that point onwards \(if possible\) to a filesystem-specific unique form. It should return the character index one beyond where is could no longer apply \(e.g. pointing to a directory separator or end of string\). That index is then passed on to the next filesystem to continue. Most filesystems do not support path ambiguity, in which case the function need not be implemented at all \(a NULL entry in the lookup table is acceptable\). For example on Windows, the path "c:/PROGRA~1/tcl/tclkit.exe/lib" would be modified to "C:/Program Files/Tcl/tclkit.exe/lib" by the core's normalization procedure, which would return '31', pointing to the '/' in-between .exe and lib. File manipulation: For each filesystem function which is implemented, these procs should be declared: TclfsAccessProc_ *accessProc; TclfsStatProc_ *statProc; TclfsOpenFileChannelProc_ *openFileChannelProc; TclfsMatchFilesTypesProc_ *matchFilesTypesProc; TclfsLstatProc_ *lstatProc; TclfsCopyFileProc_ *copyFileProc; TclfsRenameFileProc_ *renameFileProc; TclfsCopyDirectoryProc_ *copyDirectoryProc; TclfsDeleteFileProc_ *deleteFileProc; TclfsCreateDirectoryProc_ *createDirectoryProc; TclfsRemoveDirectoryProc_ *removeDirectoryProc; TclfsLoadFileProc_ *loadFileProc; TclfsReadlinkProc_ *readlinkProc; TclfsListVolumesProc_ *listVolumesProc; TclfsFileAttrStringsProc_ *fileAttrStringsProc; TclfsFileAttrsGetProc_ *fileAttrsGetProc; TclfsFileAttrsSetProc_ *fileAttrsSetProc; TclfsUtimeProc_ *utimeProc; In fact, copy/rename file need not be implemented, because Tcl will fallback: from rename to copy and delete, and from copy to open-r/open-w/fcopy/mtime when necessary. However a filesystem may well be able to implement these more efficiently than that. Cd/pwd support: TclfsChdirProc_ *chdirProc; TclfsGetCwdProc_ *getCwdProc; the chdir proc need only return TCL\_OK if the path is a valid directory, and TCL\_ERROR otherwise. There is no need to remember the path in any way. Native filesystems will of course want to make the appropriate system calls to change the real cwd. Most filesystems will not implement the 'Cwd' proc, since Tcl keeps track of the cwd for you. However, the native filesystem should implement it. Unload file support: TclfsUnloadFileProc_ *unloadFileProc; This function is called automatically by Tcl's core to unload a file, _if_ this filesystem was the one which successfully loaded the file initially. # Philosophy This TIP is influenced by the thoughts behind the TkGS project \(<http://sourceforge.net/projects/tkgs/\).> Whereas TkGS provides a general and efficient graphics system, the aim of this TIP is to provide a similarly general and efficient filesystem. # Alternatives 1. Alternatives to adding vfs support > TclKit manages a pretty good job of vfs support. It is limited by the inadequacy of overriding at the Tcl level. Prowrap is limited by the inability to glob, load, cd, pwd, etc. > There are currently no better alternatives: if Tcl's C core calls C functions directly \(as it does\), or if extensions call C functions directly \(as they do\), then complete vfs support requires a patch like this to Tcl's core. 2. Alternatives to objectification > A previous patch added string-based vfs support to Tcl's core, and required very few core changes at all. It could be adopted instead of an objectified filesystem. This would make Tcl's filesystem more complete, but would not make it any more efficient. Also it is much harder to implement complete 'glob' emulation without the newer API. # Objections _Won't all these hooks slow down Tcl's core a lot?_ There are actually remarkably few changes required, so the only slowdown would occur if additional filesystems are hooked into the core. This is similar to the impact of the 'stacked channels' implementation. With the objectified filesystem, this does actually speed up Tcl's core \(as remarked above, 'file exists' is 20% faster on Windows 2000\). _Won't this break backwards compatibility \("The Tcl question"\)?_ Not at all. With the current vfs patch, the entire test suite passes as before, even with an extra 'reporting' filesystem activated. Most reasonable tests now pass even when the test suite is embedded in a wrapped document. _Won't this make Tcl's core more complex??_ Adding a Tcl\_Obj interface is definitely a bit more complex in some areas than the existing string-based system, but in other areas it cleans things up a lot. Indeed, one result will be that Tcl's filesystem is properly abstracted away, which conceptually simplifies the core \(there will be 10-15 functions which are called for _all_ filesystem access, whether it is native or virtual\). # Future thoughts This section contains items which are outside the scope of this TIP, but it was thought useful to raise and have documented for the record. * Should we remove the native 'Tclpxx' filesystem functions from Tcl's API? Or perhaps require a new \#define TCL\_PROVIDE\_NATIVE\_FILESYSTEM to allow an extension to access these calls? They are all inside tclInt.h, so we could easily protect them with such a define. This patch still places the native filesystem in a preferential position, and it is hard-coded as the tail of the fs-lookup list. There are two changes which could be made in the future: * Move the native-fs support to a static extension which is loaded on startup. This would ensure the layer now separating Tcl from the native FS is not violated, and might let others use Tcl or pieces of Tcl in new ways. * By incorporating some pieces of the 'vfs' extension into the core in the future, and probably making some changes to some of the Tclp native-fs functions, we could make Tcl entirely filesystem-agnostic \(e.g. we could do weird things like mount the native filesystem inside a virtual filesystem\). Alternatively, if the native filesystem is not loaded at all, that makes for a very good way to ensure a wrapped executable is 'safe', because it cannot even access the local disk. Also, * Once prowrap is updated to use the new APIs, we should probably remove the primitive vfs hooks it currently uses, this will remove some obsolete stuff from Tcl's core without affecting anything else \(I think - any extensions out there use those APIs?\). Prowrap simply needs to register a Tcl\_Filesystem with the stat, access and openfilechannel fields set to its existing procedures; all other fields can be NULL. \(They would also need to be objectified\). * file copy can now potentially copy across filesystems, which could be both very slow \(across the internet\) and may even want different eol conventions on each end. We could add a _-command_ flag to _file copy_ \(and perhaps _file rename_\), and we could perhaps add optional ways of specifying the encoding/translation of the transfer? \(The main issue is to distinguish between text and binary files, which require automatic and binary _-translation_ respectively\). # Copyright This document has been placed in the public domain. |
Name change from tip/170.tip to tip/170.md.
|
| < | < | | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | < > | | | | | | | | < > | < | > | | | | | | | < > | < | | > > | 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 | # TIP 170: Better Support for Nested Lists Author: Sergey Babkin <[email protected]> Author: Don Porter <[email protected]> Author: Donal K. Fellows <[email protected]> State: Draft Type: Project Vote: Pending Created: 30-Jan-2004 Post-History: Tcl-Version: 8.7 ----- # Abstract Nested lists are easy to create with Tcl but then manipulating them is not easy. For example, think about how to change a value nested in a list 2 levels deep? How about 4 levels deep? The proposed new commands make such manipulation easy, and make the nested lists a great replacement for arrays and structures in C-like languages. # Rationale and Specification The new proposed commands start with the prefix "ldeep". They are desgined to resemble the classic list commands with "l" names. In the cases when the meaning of "ldeep" command differs substantially from the "l" command, the name has been selected to be different \(such as "ldeeprep", not "ldeepreplace"\). The commands have been extensively used in the Not A Commander project <http://nac.sf.net/> and have been adjusted to the observed needs of practical use. All these commands use the concept of "path" \(see [[22]](22.md)\) and handle the concatenation of paths for reasons of convenience \(e.g. a "base" path followed by a "local" path\). ## Commands The new proposed commands are: > **ldeepset** _listvar path_ ?_path_?... _value_ Set a _value_ in a nested list variable. If the variable did not exist previously, it is created. If the intermediate lists specified in the path did not exist, they are created as empty lists. This includes the "filler" elements: for example, if _listvar_ contained a list of one element and the path starts with "5 ...", the elements with indexes 1, 2, 3, 4 and 5 will all be created \(and will contain empty strings\) and the the further creation within the element at index 5 will proceed. A special meaning is assigned by this command to the negative indexes in the path: they mean "add a new element at the end of the list". So this command also doubles as a nested version of lappend. For example, ldeepset listvar -1 value means the same thing as lappend listvar value This merging has happened because it's often neccessary to add elements to the lists in the middle of the path. The particular value used to indicate the addition of an element can be changed to something more symbolic, for example to "append" instead of a negative value. The _ldeepset_ command returns nothing. Since the version without value as in the common set can not be used, returning the value did not seem to make sense. Also when experimenting with large lists from the command line, returning the value that is a large list itself would cause a long and unpleasant printout of it. _\(This is only partially superceded by [[33]](33.md) and [[331]](331.md).\)_ > **ldeepincr** _lstvar path_ ?_path_?... _int-value_ Increase a value within a nested list by _int-value_. Note that since the amount of increase has to be differentiated from the _path_, it's mandatory even for the value of 1. This is a convenient and often used shortcut for the **ldeepindex**-**expr**-**ldeepset** sequence. It returns the value of the element after increase. > **ldeeprep** _lstvar path_ ?_path_?... _first last element-list_ Replace a range of elements in a sublist identified by the _path_ with the elements from the _element-list_. It returns nothing. This command is different from **lreplace** in two ways, hence the name change. First, it acts on data in a variable, not on a list as an argument. Second, the elements for replacement are contained in a list, not as separate elements on command line. Both differences were created for convenience of practical use, plus to allow the path to pick up the variable number of arguments. I have found that I always need to replace elements in a variable, not as a pass-through operator, and that I almost always need to insert elements from another list, not just some fixed set of elements. > **ldeeppop** _lstvar path_ ?_path_?... _count_ Remove _count_ elements from the end of the sublist identified by _path_ in the variable and return them in a list. This command was inspired by the pop operator in Perl. Somehow I've never has a very string need for the other similar commands \(which would be _ldeeppush_ to add elements, and _ldeepshift_ and _ldeepunshift_ for operations on the start of the list\) but they can be easily added as well for completeness. The command returns the list of the popped elements in the original order. For example, if _lstvar_ contained \{0 1 2 3 4 5\}, "ldeeppop lstvar \{\} 2" would return \{4 5\}, NOT \{5 4\}. # Other Extensions for List Support In my practice I have found that a few other commands make working with lists much more convenient. They are not directly related to the nested lists but to the lists in general. > **lconcat** _sublist_ ?_sublist_?... Concatenate the argument lists and return the resulting list. This command is similar to **concat** but avoids converting the values to strings, concatenating the strings and then re-parsing the strings. When the lists involved grow to a few megabytes, **concat** can become very inefficient both in the sense of time and memory usage; **lconcat** resolved this inefficiency. Note that it does _not_ replace **concat**, which can be used to assemble lists from pieces in different argument strings. The command returns the concatenated list. _\(Note that this is largely possible through using_ **list** _and [[157]](157.md)/[[293]](293.md), and that_ **concat** _is more likely to handle the lists where this matters efficiently anyway right now due to efficiency tweaks to its implementation. It remains to be seen whether there is still a need for_ **lconcat** _in other areas...\)_ # Reference Implementation The reference implementation is available as part of the Not A Commander project <http://nac.sf.net/> , the source file _cutil.c_. To include the new commands into Tcl, the error messages will have to be adjusted to match the style used in Tcl, and the man pages will have to be written. The current implementation has been tested in fair amounts for both correctness and efficiency by usage in the Not A Commander project, the formal test suite would have to be written. Further progress in this direction depends on acceptance of this proposal. # Comments Messages on the TCLCORE mailing list have pointed out that nearly everything proposed here is either equivalent to, or trivially created by composition of the existing commands **lindex**, **lrange**, **lset**, **lassign**, and **lrepeat**. The only novel thing proposed is the ability of **lset** to create new list elements. If that's still desired, a separate new TIP proposing that alone would be the best way to deal with that. I call on the author to withdraw this TIP. # Copyright This document has been placed in the public domain. ---- # Appendix: Removed Commands _These commands were originally part of this TIP, but have been removed to this appendix on the grounds that the functionality they describe is now part of Tcl via other TIPs._ > **ldeepindex** _list path_ ?_path_?... Extract an element from a nested list. The element is identified by the logical concatenation of the paths. It returns the extracted element. _\(Obsoleted by [[22]](22.md).\)_ > **ldeeplen** _list path_ ?_path_?... Find the length of a nested sublist. The sublist is identified by the logical concatenation of the paths. It returns the found length. A non-existing sublist is assumed to have the length of 0. _\(Obsoleted by [[22]](22.md) and normal llength.\)_ > **ldeeprange** _list path_ ?_path_?... _first last_ Extract a sublist from a nested list. This command is a convenient equivalent of lrange [ldeepindex list path ?path?] first last] "end" is supported as the first or last index. It returns the extracted sublist. _\(Obsoleted by [[22]](22.md) and normal lrange.\)_ > **mset** _list-of-variable-names list-of-values_ Set the values from the value list to the variable in the variable list at the same index. The command name stands for "multiple set". This command is inspired by assignments in Perl. If there were more variables than the values, the rest of variables are set to an empty value. If there were more values than variables, then the last variable is assigned the whole end of a list \(as a list\). A special variable name "**-**" can be used to throw away a value, or the whole end of the value list if it's specified as the last one in the variable list. The command returns nothing. It can be argued that it would make sense to return the length of the original list, or the difference between the length of the values list and the length of the variables list. I don't know which one is better. This command is particularly convenient for returning multiple values from a procedure. For example: proc xxx {a b} { return [list [expr $b+$a] [expr $b*$a]] } mset {sum product} [xxx 1 2] _\(Obsoleted by [[57]](57.md).\)_ > **ldup** _count element_ ?_element_?... This returns a list produced by duplicating the sequence of elements _count_ times. This command is inspired by the operator "x" in Perl, and it is a logical equivalent of: proc ldup {count args} { set res {} for {set i 0} {$i < $count} {incr i} { set res [lconcat $res $args] } return $res } _\(Obsoleted by [[136]](136.md).\)_ > **lvdup** _count element-list_ This returns a list produced by duplicating the _element-list count_ times. This command is inspired by the operator "x" in Perl, and it is a logical equivalent of: proc lvdup {count list} { set res {} for {set i 0} {$i < $count} {incr i} { set res [lconcat $res $list] } return $res } _\(Obsoleted by [[136]](136.md) and [[157]](157.md)/[[293]](293.md).\)_ |
Name change from tip/171.tip to tip/171.md.
|
| < | < | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | < > | | | | | < > | | | | | | | | | | | < < < < > > > > | | | | | | | < | > | | | | | | | | | < < | > > | | | | | > | 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 | # TIP 171: Change Default <MouseWheel> Bindings Behavior Author: Jeff Hobbs <[email protected]> Author: Keith Vetter <[email protected]> State: Final Type: Project Vote: Done Created: 05-Mar-2004 Post-History: Tcl-Version: 8.6 ----- # Abstract This TIP proposes changing the default <MouseWheel> bindings in Tk to have "better" behaved defaults for a larger set of applications. # Rationale The existing <MouseWheel> bindings only operate on a small handful of widgets, and only when they have focus. This essentially means that only the text widget ever has useful <MouseWheel> behavior. This is not how the majority of applications wish to use the MouseWheel. They operate primarily on a mouse-focus model \(scroll what the mouse is over, not what has **focus**\). In addition, <Shift-MouseWheel> horizontal scrolling support is added. # Specification The bindings changes are very simply these: proc ::tk::MouseWheel {wFired X Y D {shifted 0}} { # Set event to check based on call set evt "<[expr {$shifted?{Shift-}:{}}]MouseWheel>" # do not double-fire in case the class already has a binding if {[bind [winfo class $wFired] $evt] ne ""} { return } # obtain the window the mouse is over set w [winfo containing $X $Y] # if we are outside the app, try and scroll the focus widget if {![winfo exists $w]} { catch {set w [focus]} } if {[winfo exists $w]} { if {[bind $w $evt] ne ""} { # Awkward ... this widget has a MouseWheel binding, but to # trigger successfully in it, we must give it focus. catch {focus} old if {$w ne $old} { focus $w } event generate $w $evt -rootx $X -rooty $Y -delta $D if {$w ne $old} { focus $old } return } # aqua and x11/win32 have different delta handling if {[tk windowingsystem] ne "aqua"} { set delta [expr {- ($D / 30)}] } else { set delta [expr {- ($D)}] } # scrollbars have different call conventions if {[string match "*Scrollbar" [winfo class $w]]} { catch {tk::ScrollByUnits $w \ [string index [$w cget -orient] 0] $delta} } else { set cmd [list $w [expr {$shifted ? "xview" : "yview"}] \ scroll $delta units] # Walking up to find the proper widget handles cases like # embedded widgets in a canvas while {[catch $cmd] && [winfo toplevel $w] ne $w} { set w [winfo parent $w] } } } } bind all <MouseWheel> [list ::tk::MouseWheel %W %X %Y %D 0] bind all <Shift-MouseWheel> [list ::tk::MouseWheel %W %X %Y %D 1] if {[tk windowingsystem] eq "x11"} { # Support for mousewheels on Linux/Unix commonly comes through # mapping the wheel to the extended buttons. bind all <4> [list ::tk::MouseWheel %W %X %Y 120] bind all <5> [list ::tk::MouseWheel %W %X %Y -120] } Instead of requiring a widget to have **focus** to receive MouseWheel events, the new proposal operates with MouseWheel as a global binding. When fired, it first does a safety check to prevent double-firing if an existing MouseWheel binding is on the widget. It then finds the widget which the mouse if over and uses that as the target for the scrolling event. If that widget doesn't exist \(usually meaning that it returned \{\} indicating we are outside the Tk app\), then use the widget which has the actual **focus**. In scrolling, the scrollbar must be treated separately, since it has its own calling conventions. All others widgets get called with the standard yview scroll command, caught in case of errors, which are ignored. This has been discussed on the tcl-mac mailing list already as the desired behavior, and confirmed to be more intuitive on Windows as well. The above code is already in use by applications that use widget extensions and megawidgets such as BWidgets without any adverse effects seen. Note that the existing MouseWheel bindings must first be removed, using the following code: set mw_classes [list Text Listbox Table TreeCtrl] foreach class $mw_classes { bind $class <MouseWheel> {} } if {[tk windowingsystem] eq "x11"} { foreach class $mw_classes { bind $class <4> {} bind $class <5> {} } } # Reference Implementation See above. # Discussion Shift-MouseWheel was added after initial discussion. Use of "\*Scrollbar" is to catch TScrollbar as well. This is adapted from tklib/style/as.tcl mousewheel adjustments and has proved useful and workable across a variety of applications. There is a bit of awkwardness in handling widgets that have their own MouseWheel bindings in that core Tk requires these have focus to receive the event. It may be better to fix this forced limitation in Tk rather than the special-case code above \(although that code does work\). # Copyright This document has been placed in the public domain. |
Name change from tip/172.tip to tip/172.md.
|
| < | < | | | | | | | | > | | | | | | | > | 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 | # TIP 172: Improve UNIX Tk Look and Feel Author: David N. Welton <[email protected]> State: Withdrawn Type: Project Vote: No voting Created: 08-Mar-2004 Post-History: Tcl-Version: 8.5 Obsoleted-By: 248 ----- # Abstract In the spirit of "worse is better", this TIP proposes a simple way to notably improve Tk's look and feel for the 8.5 release of Tk. It does not fix all the problems, and won't make Tk look like whatever toolkit is "native" on the user's machine \(Gtk or Qt\), but will at least improve the current situation. # Rationale This TIP is needed because people continue to complain about Tk's outdated look. This TIP, being extremely easy to implement, should be put into place while we await a technically superior solution such as the Tile project. # Proposed Change The two things that ought to happen are as follows: 1. The code now located in the tklib "style" module should be tweaked to further improve its look \(for instance Pat Thoyts suggests a few additional improvements at the bottom of the page\), and included as the default look for Tk on Unix in the 8.5 release. Credit goes to Jeremy Collins and the Tk revitalization project for most of the code, I believe. 2. A loadable package should be distributed with Tk that reverts the look and feel to "classic Tk", so that "package require classictk" would be the only change necessary to not use the new look. # Copyright This document has been placed in the public domain. |
Name change from tip/173.tip to tip/173.md.
|
| < | < | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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 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 | # TIP 173: Internationalisation and Refactoring of the 'clock' Command Author: Kevin Kenny <[email protected]> State: Final Type: Project Vote: Done Created: 11-Mar-2004 Post-History: Discussions-To: news:comp.lang.tcl Tcl-Version: 8.5 ----- # Abstract The [clock] command provides Tcl's fundamental facilities for computing with dates and times. It has served Tcl faithfully since 7.6, but the computing world has advanced significantly in the decade that it has been in service. This TIP proposes a \(nearly entirely compatible\) reimplementation of [clock] that will allow for fewer ambiguities on input, improved localisation, more portability, and less exposure of platform-dependent bugs. A significantly greater fraction of [clock] shall be implemented in Tcl than it is today, and the code shall be refactored to use the ensemble mechanism introducted for Tcl 8.5 \(see [[112]](112.md)\). # Rationale There is an embarrassing number of open bugs and feature requests against the [clock] command. As the maintainer of [clock], the author of this TIP has also received a number of informal feature requests that are not logged at SourceForge. Unfortunately, many of the requested fixes and enhancements cannot be effectively addressed with the current architecture of [clock]. 1. Several users have requested additional input formats to [clock scan], notably the full range of ISO8601 time formats \(including formats based on week number and day-of-week\); year and day-of-year; Apache "web log" dates and times; numeric dates placing the month before the day; and localised names of months and days of the week. Unfortunately, these formats simply cannot be added in the current architecture of [clock scan]; in fact, there are several outstanding bugs in [clock scan] \(for example, the parsing of numeric time zones east of Greenwich\) that cannot be fixed without breaking something else. > The fundamental issue is that [clock scan] is asked to process input with too many ambiguities. An input token such as _2000_, for example, may be interpreted as a year, a time of day, or a number \("now \+ 2000 seconds"\). _1000_ may \(perhaps\) not be a year, but could be a time of day, a number, or a time zone. Localisation would only make this problem worse. Without additional guidance, there is, even in theory, no way to determine whether _03-11-2004_ represents the third of November or the eleventh of March. > To solve this problem, a radical redesign of [clock scan] is required; the programmer _must_ be allowed to specify an expected input format \(or set of expected formats\). > A side effect of such a redesign would be improved ease of maintenance. The current [clock scan] is a YACC-derived parser; the build process, however, runs a script on the output of YACC to modify its memory management and alter its external symbol names to make it compatible with Tcl's conventions. This script is fragile; at present, it is known to work only with the version of YACC distributed with Solaris. > There are a number of other issues with [clock scan] that could be addressed at the same time with such a redesign. For instance, there is a known problem at present that an input string that specifies time and time zone but not date can return a time that is one day too early or late; this problem arises because the existing parser presumes the current _local_ date when parsing such a string, rather than the current date in the given time zone. The problem is difficult to address because of the left-to-right nature of the LALR\(1\) parser. 2. A few enhancements have been requested to [clock format]; most notably, proper localization on all platforms. In addition, the documentation of [clock format] is at best approximate, because it depends on the _strftime_ function in the Standard C Library. This function differs among platforms, because the C standard, the Posix standard, and the Single Unix Specification have gone through evolution over time, and few platforms support all the features of the current generation of any of them. > In addition, the Year 2038 bug looms large on the horizon. On most 32-bit platforms, _time\_t_ \(used in the C library funtions\) is a 32-bit count of seconds from 1 January 1970; dates beyond 2038 cannot be represented in this format. > The dependence on a complex library function such as _strftime_ introduces obscure platform-dependent bugs. Several open bugs in [clock format], for instance, fail only on HP-UX, or only on Windows. > Date formats have been requested \(specifically, the Japanese civil calendar\) that are beyond the capabilities of the Standard C Library functions. > [clock format] does not honor user preferences for date/time format on Windows. > All of these concerns seem to indicate that our current dependency upon vendor-supplied date and time manipulation routines is ill advised. A single implementation that we control will make the behavior consistent among platforms, allow the localisation to follow Tcl's conventions, and let us lead rather than follow the vendor in fixing bugs. 3. Server applications frequently require support of multiple locales and multiple time zones within a single process, because they need to parse input and format output according to the client's environment. The current [clock] facilities either do not support localization at all, or else support a change to locale only by changing environment variables. This technique, once again, exposes bugs in the vendor libraries. It also introduces difficulties with thread safety; Tcl does not have a single mechanism whereby the _TZ_ and _LC\_TIME_ environment variables are protected. 4. The only mechanism for performing calculations like "one month after the current date" is [clock scan]. While this works well in practice, using a parser to perform arithmetic seems somewhat perverse. # Specification The [clock] command shall be reimplemented as an ensemble [[112]](112.md), with most of the subcommands implemented in Tcl. A minimal set of the existing C code shall be refactored and placed inside a _::tcl::clock_ namespace. The existing subcommands _seconds_ and _clicks_ shall be exposed. The existing _scan_ shall be hidden inside the namespace. [clock scan] and [clock format] shall be reimplemented in Tcl. In addition, a new [clock add] command shall be added. The syntax and semantics of the [clock clicks] and [clock seconds] commands will remain unchanged. ### clock scan The [clock scan] command shall have the syntax: > **clock scan** _string_ ?**-base** _baseTime_? ?**-format** _format_? ?**-gmt** _boolean_? ?**-locale** _name_? ?**-timezone** _timeZone_? It accepts a character string representing a date and time and returns the time that the string represents, expressed as a count of seconds from the Posix epoch \(1 January 1970, 0000 UTC\). If a **-format** option is not supplied, the scan is a _free format_ scan. The existing YACC parser for _clock scan_ will be used to interpret the input string. _This form of the command is explicitly deprecated_ because of the inherent ambiguities in interpreting the input string. The free-format version of [clock scan] does not accept **-locale** or **-timezone** options, since the legacy code does not support multiple locales or time zones. If the **-format** options is supplied, it is interpreted as a specification for the expected input form. If the given string matches the input form, it is converted to a count of seconds and returned; otherwise, an error is thrown. See _FORMATS_ below for a discussion of the available format groups and their interpretation. Extraction of the date from the input string is guided by what fields are present in the format. The order of preference, from highest to lowest, is: \{seconds from epoch\}, \{starDate\}: Date fields that specify both date and time take highest precedence. If format groups for these fields appear multiple times, the rightmost takes precedence. \{Julian Day Number\}: The Julian Day Number uniquely specifies a calendar date. \{century, year, month, day of month\}, \{century, year, day of year\}, \{century, year, week of year, day of week\}, \{locale era, locale year, month, day of month\}: Formats with complete year are preferred to formats with a two-digit year. For a two digit year, the date range is constrained to lie between 1938 and 2037. \{year, month, day of month\}, \{year, day of year\}, \{year, week of year, day of week\}, \{year of locale era, month, day of month\}: Formats that specify the year are preferred to those that do not. \{month, day of month\}, \{day of year\}, \{week of year, day of week\}: Formats that specify a day within the year are preferred to those that specify merely the day of week or day of month. Formats that do not specify the year are presumed to designate the base year. \{day of month\}, \{day of week\}: If none of the above rules apply, a day of the month or day of the week standing alone is interpreted as belonging to the base month or week. None of the above: If no combination of fields that specifies a date is found, the base date is used. The time of day returned by [clock scan] is determined by the presence of fields in the format string, in the following order of preference. \{seconds from epoch, StarDate\}: If either of these fields is present, it uniquely determines date and time. \{am/pm indicator, hour am/pm, minute, second\}, \{hour, minute, second\}: Time with seconds is preferred to time without seconds. \{am/pm indicator, hour am/pm, minute\}, \{hour, minute\}: Time can be interpreted without the seconds. \{am/pm indicator, hour am/pm\}, \{hour\}: Time can be expressed as an hour alone, _e.g._, clock scan "6 pm" -format "%I %p" None of the above: If none of the above indicators is present, _00:00:00_ \(the start of the day\) in the given time zone is used. In all of the foregoing discussion, the 'base date', 'base month', 'base week', and 'base year' refer to the day, month, week or year designated by the **-base** parameter, which is a count of seconds from the Posix epoch. If no **-base** parameter is supplied, the current date is used as the base date. The year, month, week and day are obtained by interpreting the base date in the time zone specified by the date/time string. If the given format does not include a time zone, then the base time is interpreted in the default time zone; see _TIME ZONES_ below for the way that the default time zone is determined, and the interpretation of the **-timezone** and **-gmt** options. The locale is used to determine the spelling of native language words such as the names of months, names of weekdays, am/pm indicators, and locale eras. It is also used in the interpretation of the format groups, '%X', '%x', and '%c'. In addition, the locale determines the date at which the calendar in use changes from the Julian calendar to the Gregorian. If no **-locale** parameter is supplied, the default is to use the root locale. See _LOCALISATION_ below for more information. ### clock format The [clock format] command shall have the syntax: > **clock format** _string_ ?**-format** _format_? ?**-gmt** _boolean_? ?**-locale** _name_? ?**-timezone** _timeZone_? It accepts a time, expressed in seconds from the Posix epoch of 1 January 1970, 00:00 UTC, and formats it according to the given format string. See _FORMATS_ below for a discussion of the available format codes. If no format string is supplied, a default format, \{%a %b %d %H:%M:%S %Z %Y\} is used. The **-timezone**, **-gmt**, and **-locale** options are interpreted as for [clock scan]. See _TIME ZONES_ and _LOCALISATION_ below for how these options work. ### clock add This command performs arithmetic on dates and times. The syntax is: > **clock add** _time_ ?_count unit_?... ?**-gmt** _boolean_? ?**-timezone** _timeZone_? ?**-locale** _name_? It accepts a time, expressed in seconds from the Posix epoch of 1 January 1970, 00:00 UTC, and adds or subtracts units of time from it according to the alternating _count_ and _unit_ parameters. Each _count_ must be a wide integer; each _unit_ is one of the following: years year months month weeks week days day hours hour minutes minute seconds second The command works by converting the given time to a calendar day and time of day in the given locale and time zone. To that day and time of day, it adds or subtracts the given offsets _in sequence_. It reconverts the resulting time to a count of seconds, again using the given locale and time zone, and returns that count of seconds. There are subtle differences in many cases between adding seemingly similar offsets. For instance, on the day before Daylight Saving Time goes into effect, adding 24 hours will give "the time 24 hours from the base time, irrespective of any clock change", while adding 1 day will give "the time it will be at the same time of day on the following day." Similarly, adding 1 month on 30 January will give either 28 or 29 February. There are equally strange effects when performing date/time arithmetic across the change between the Julian and Gregorian calendars. The **-timezone**, **-gmt**, and **-locale** options are used to control the interpretation of the count of seconds as a calendar day and time. Refer to _TIME ZONES_ and _LOCALIZATION_ below for a fuller discussion. ## Formats The [clock scan] and [clock format] commands will be implemented in Tcl, without depending on the local _strftime_ and _strptime_ functions. For this reason, format groups will function identically on all platforms. The format groups will be interpreted as follows. %a: On output, receives the abbreviation for the day of the week in the given locale. On input, matches the name of the day of the week \(in the given locale\) in either abbreviated or full form, and may be used to determine the calendar date. %A: On output, receives the full name of the day of the week in the given locale. On input, treated identically with %a. %b: On output, receives the abbreviation for the name of the month in the given locale. On input, matches the name of the month \(in the given locale\) in either abbreviated or full form, and may be used to determine the calendar date. %B: On output, receives the full name of the month in the given locale. On input, treated identically with %b. %C: On output, receives the number of the century, in Indo-Arabic numerals. On input, matches one or two digits, and accepts the number of the century in Indo-Arabic numerals. May be used to determine the calendar date. %c: On output, produces a correct locale-dependent representation of date and time of day. On input, matches whatever format _%c_ produces in the given locale, and may be used to determine calendar date and time. %d: On output, produces the number of the day of the month, in Indo-Arabic numerals, with a leading zero. On input, matches one or two digits, accepts the day of the month, and may be used to determine calendar date. |
︙ | ︙ | |||
359 360 361 362 363 364 365 | and may be used to determine calendar date. %EX: On output, produces the time of day in the locale's alternative representation. On input, accepts whatever %EX produces and may be used to determine time of day. %Ey: On output, produces the number of the current year relative to | | | 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 | and may be used to determine calendar date. %EX: On output, produces the time of day in the locale's alternative representation. On input, accepts whatever %EX produces and may be used to determine time of day. %Ey: On output, produces the number of the current year relative to the locale's current era _%EC_, expressed in the locale's alternative numerals. On input, accepts the number of the year relative to the current era in the locale's alternative numerics, and may be used to determine calendar date. %EY: On output, produces an unambiguous representation of the current year in the locale's alternative calendar and alternative numerals. This group is often synonymous with %EC%Ey. On |
︙ | ︙ | |||
383 384 385 386 387 388 389 | with the ISO8601 week number. On input, accepts a four-digit year number, and may be used to determine calendar date if the %V format group is also present. %h: Synonymous with %b. %H: On output, produces the two-digit hour of the day on a 24-hour | | | | | | | | | | | | | | | | | | | | | 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 | with the ISO8601 week number. On input, accepts a four-digit year number, and may be used to determine calendar date if the %V format group is also present. %h: Synonymous with %b. %H: On output, produces the two-digit hour of the day on a 24-hour clock \(00-24\). On input, matches two digits, and may be used to determine time of day. %I: On output, produces the two-digit hour of the day on a 12-hour clock \(12-11\). On input, matches two digits, and may be used to determine time of day. %j: On output, produces the three-digit number of the day of the year. On input, matches three digits, and may be used to determine the day of the year. %J: On output, produces the number of the Julian Day Number beginning at noon of the given date. The Julian Day Number is a representation popular with astronomers; it is a count of days in which Day 1 is 1 January, 4713 B.C.E., on the proleptic Julian calendar; in this system, 1 January 2000 is Julian Day 2451545. On input, matches any string of digits and interprets it as a Julian Day; may be used to determine calendar date. %k: On output, produces the number of the hour on a 24-hour clock \(0-24\) without a leading zero. On input, matches one or two digits and may be used to determine time of day. %l: On output, produces the number of the hour on a 12-hour clock \(12-11\) without a leading zero. On input, matches one or two digits and may be used to determine time of day. %m: On output, produces the number of the month \(01-12\), with exactly two digits \(using a leading zero if necessary\). On input, matches exactly two digits and may be used to determine calendar date. %M: On output, produces the number of the minute of the hour \(00-59\) with exactly two digits \(using a leading zero if necessary\). On input, matches exactly two digits and may be used to determine time of day. %N: On output, produces the number of the month, with no leading zero. On input, matches one or two digits, and may be used to determine time of day. %Od, %Oe, %OH, %OI, %Ok, %Ol, %Om, %OM, %OS, %Ou, %ow, %Oy: All of these format groups are synonymous with their counterparts without the 'O', except that the string is produced and parsed in the locale-dependent alternative numerals. %p: On output, produces the indicator for 'a.m.', or 'p.m.' appropriate for the given locale, converted to upper case. On input, accepts whatever %p produces \(in upper or lower case\) and may be used to determine time of day. %P: On output, produces the indicator for 'a.m.', or 'p.m.' appropriate for the given locale. On input, accepts whatever %p produces \(in upper or lower case\) and may be used to determine time of day. %Q: On output, produces a StarDate. On input, accepts a StarDate and may be used to determine calendar date and time of day. %r: On output, produces a locale-dependent time of day representation on a 12-hour clock. On input, accepts whatever %r produces and may be used to determine time of day. %R: On output, produces a locale-dependent time of day representation on a 24-hour clock. On input, accepts whatever %R produces and may be used to determine time of day. %s: On output, produces a string of digits representing the count of seconds since 1 January 1970, 00:00 UTC. On input, accepts a string of digits and accepts it as such a count; may be used to determine date and time of day. %S: On output, produces a two-digit number of the second of the minute \(00-59\). On input, accepts two digits. May be used to determine time of day. %t: On output, produces a TAB character. On input, matches a TAB character. %T: Synonymous with %H:%M:%S. %u: On output, produces the number of the day of the week \(1-Monday,7-Sunday\). On input, accepts a single digit. May be used to determine calendar day. %U: On output, produces the ordinal number of the week of the year \(00-53\). The first Sunday of the year is the first day of week 01. On input accepts two digits _which are otherwise ignored._ This format group is never used in determining an input date. %V: On output, produces the number of the ISO8601 week as a two digit number \(01-53\). Week 01 is the week containing January 4; or the first week of the year containing at least 4 days; or the week containing the first Thursday of the year \(the three statements are equivalent\). Each week begins on a Monday. On input, accepts the ISO8601 week number, and may be used to determine the calendar day. %w: On output, produces a week number \(00-53\) within the year; week 01 begins on the first Monday of the year. On input, accepts two digits, _which are otherwise ignored._ This format group is never used in determining an input date. %x: On output, produces the date in a locale-dependent representation. On input, accepts whatever %x produces and may be used to determine calendar date. %X: On output, produces the time of day in a locale-dependent |
︙ | ︙ | |||
505 506 507 508 509 510 511 | %Y: On output, produces the four-digit calendar year. On input, accepts four digits and may be used to determine calendar date. Note that %Y does not yield a year appropriate for use with the ISO8601 week number %V; programs should use %G for that purpose. %z: On output, produces the current time zone, expressed in hours and | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | < > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 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 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 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 | %Y: On output, produces the four-digit calendar year. On input, accepts four digits and may be used to determine calendar date. Note that %Y does not yield a year appropriate for use with the ISO8601 week number %V; programs should use %G for that purpose. %z: On output, produces the current time zone, expressed in hours and minutes east \(\+hhmm\) or west \(-hhmm\) of Greenwich. On input, accepts a time zone specifier \(see _TIME ZONES_ below\) that will be used to determine the time zone. %Z: On output, produces the current time zone's name, possibly translated to the given locale. On input, accepts a time zone specifier \(see _TIME ZONES_ below\) that will be used to determine the time zone. _This option should, in general, be used on input only when parsing RFC822 dates._ Other uses are fraught with ambiguity; for instance, the string _BST_ may represent _British Summer Time_ or _Brazilian Standard Time_. It is recommended that date/time strings for use by computers use numeric time zones instead. %%: On output, produces a literal '%' charater. On input, matches a literal '%' character. %\+: Synonymous with "%a %b %e %H:%M:%S %Z %Y". ## Time Zones There are several ways that a time zone may be specified for use with [clock scan], [clock format] and [clock add]. In order of preference: * The time zone may appear in the input string matched by a %z or %Z format group in [clock scan]. These format groups match time zones in the forms \+hhmm, \+hhmmss, -hhmm, -hhmmss, and alphanumeric strings. The numeric representations are self explanatory; an alphanumeric string must be the one of: gmt ut utc bst wet wat at nft nst ndt ast adt est edt cst cdt mst mdt pst pdt yst ydt hst hdt cat ahst nt idlw cet cest met mewt mest swt sst eet eest bt it zp4 zp5 ist zp6 wast wadt jt cct jst cast cadt east eadt gst nzt nzst nzdt idle > or a single letter other than J. Generally speaking, numeric time zones should be preferred for communication among computers; the alphanumeric time zones are provided primarily for the parsing of legacy RFC822 time stamps. * The time zone may appear in the **-timezone** argument to the [clock] command, or may be implied by the presence of **-gmt 1**. It is an error to use **-timezone** and **-gmt** in the same call. The **-gmt 1** option may be regarded as an obsolete synonym of **-timezone :UTC**. * The time zone may appear in the environment variable, _TCL\_TZ_. * The time zone may appear in the environment variable, _TZ_. * Failing all of these, on Windows systems, the time zone will be obtained from the Registry. * As a last resort, the time zone is set to ':localtime'. Once the time zone is obtained by one of these means, it is interpreted as follows: ":localtime": This specifier requests that the C library functions _localtime\(\)_ and _mktime\(\)_ be used whenever converting times between local and Greenwich. It is generally used as a last resort if the time zone can be determined in no other way. "\+hhmm", "\+hhmmss", "-hhmm", "-hhmmss": These specifiers give the time zone explicitly in terms of hours, minutes and seconds east \(\+\) or west \(-\) of Greenwich. ":filename": The given file name is interpreted as a path name relative to [info library]/tzdata, and the specified file is loaded as a Tcl script. The script is expected to set the _:filename_ element in the _tzdata_ array to a list of transitions. Each transition is a four-element list comprising: > \* the time at which the transition takes place, expressed in seconds from the Posix Epoch \(1 January 1970, 00:00 UTC\) > \* the offset \(in seconds east of Greenwich\) to apply. > \* an indicator \(0=Standard Time, 1=Daylight Saving Time\) > \* the name to use when displaying the given time zone in the root locale. > The first transition is expected to take place at time -9223372036854775808, the smallest value of a wide integer. Any string recognizable as a Posix time zone specifier: A time zone may be specified in Posix syntax \(see <http://www.opengroup.org/onlinepubs/007904975/basedefs/xbd_chap08.html> \), for example _EST5EDT_ or _EST\+05:00EDT\+04:00,M4.1.0/01:00,M10.5.0/02:00_. Any other string is processed by prefixing a colon and attempting to load the given file, as shown above. ## Localisation The [clock] command is localised by a set of message catalogs located in [file join [info library] clock msgs] and loaded into the namespace, ::tcl::clock. The possible strings to be translated include: AM: The string that identifies _ante meridiem_ times when expressing a time of day in the given locale. This string has the value, \{am\} in the root locale. BCE: The string that identifies dates before the Common Era in the given locale. This string has the value, \{B.C.E.\} in the root locale. Those localising this string should be aware that, depending on local culture, a name such as "B.C." \(before Christ\) may be offensive. CE: The string that identifies dates of the Common Era in the given locale. This string has the value, \{C.E.\} in the root locale. Those localising this string should be aware that, depending on local culture, a name such as "A.D." \(Latin, _anno Domini_, "in the year of Our Lord"\) may be offensive. DATE\_FORMAT: The format specifier for calendar dates in the given locale. In the root locale, %m/%d/%Y is used for compatibility with earlier versions of the [clock] command, even though %Y-%m-%d would probably be preferable. DATE\_TIME\_FORMAT: The format specifier for combined date and time in the given locale. In the root locale, \{%a %b %e %H:%M:%S %Y\} is used for compatibility with earlier versions of the [clock] command, even though %Y-%m-%dT%H:%M:%S would be preferable. DAYS\_OF\_WEEK\_ABBREV: Abbreviations of the days of the week in the given locale. In the root locale, this string has the value, \{Sun Mon Tue Wed Thu Fri Sat\}. In any locale, this string is expected to represent a valid Tcl list. DAYS\_OF\_WEEK\_FULL: Full names of the days of the week in the given locale. In the root locale, this string has the value, \{Sunday Monday Tuesday Wednesday Thursday Friday Saturday\}. In any locale, this string is expected to represent a valid Tcl list. GREGORIAN\_CHANGE\_DATE: The date on which the change from the Julian to the Gregorian calendar takes place, expressed as a Julian Day Number. In the root locale, this string has the value, \{2299161\}, corresponding to 15 October 1582 New Style. In the 'en' locale, this value is \{2361222\}, 14 September 1752 New Style. LOCALE\_DATE\_FORMAT: The format to use when formatting dates in the locale's alternative calendar. In the root locale, LOCALE\_DATE\_FORMAT is _%x_, which causes formatting without alternative numerals. LOCALE\_DATE\_TIME\_FORMAT: The format to use when formatting date/time strings in the locale's alternative calendar. In the root locale, LOCALE\_DATE\_TIME\_FORMAT is _%Ex %EX_, which causes concatenation of the locale's format for date, a space character, and the locale's format for time. LOCALE\_ERAS: In a locale where a calendar with multiple eras is in use, gives a list of triples. The first element of each triple is the time \(in seconds from the Posix epoch of 1 January 1970, 00:00 UTC\) at which the era begins; the second is the name of the era, and the third is a constant offset to be subtracted from the Gregorian year to give the year of the era. In any locale, this string is expected to represent a valid Tcl list. LOCALE\_NUMERALS: In a locale where alternative numerals may be used, gives a list containing the numerals that represent the numbers from zero to ninety-nine. Note that these numerals are the ones typically used on calendars, not the ones that represent currencies or quantities. For instance, in a Han locale, the number twenty-one is represented by \\u5eff\\u4e00, not by \\u4e8c\\u5341\\u4e00. In any locale, this string is expected to represent a valid Tcl list. LOCALE\_TIME\_FORMAT: The time format to use when formatting a time of day using a locale's alternative numerals. In the root locale, this string is _%X_, which causes formatting without alternative numerals. LOCALE\_YEAR\_FORMAT: The time format to use when formatting a year in the locale's alternative calendar. In the root locale, this string is %Y. MONTHS\_ABBREV: Abbreviated names of the months in the given locale. In the root locale, consists of three-letter abbreviations for the English months: Jan-Dec. In any locale, this string is expected to represent a valid Tcl list. MONTHS\_FULL: Full names of the months in the given locale. In the root locale, consists of the names of the English months in order from 'January' to 'December'. In any locale, this string is expected to represent a valid Tcl list. PM: The string that identifies _post meridiem_ times when expressing a time of day in the given locale. This string has the value, \{pm\} in the root locale. TIME\_FORMAT: String that specifies the default time format in the given locale. In the root locale, this string is \{%H:%M:%S\} TIME\_FORMAT\_12: String that formats time on a 12-hour clock in the given locale. In the root locale, this string is \{%I:%M:%S %p\}. TIME\_FORMAT\_24: String that formats time on a 24-hour clock in the given locale. In the root locale, this string is \{%H:%M\}. There is a defined order for substitution of locale strings, which constrains the format groups that can appear in the _\_FORMAT_ strings. Specifically: * DATE\_TIME\_FORMAT and LOCALE\_DATE\_TIME\_FORMAT may contain any format groups other than _%c_ and _%Ec_. * LOCALE\_DATE\_FORMAT and LOCALE\_TIME\_FORMAT may not contain _%c_, _%Ec_, _%Ex_, or _%EX_. * DATE\_FORMAT and TIME\_FORMAT may not contain _%c_, _%Ec_, _%x_, _%Ex_, _%X_, or _%EX_. * TIME\_FORMAT\_12 and TIME\_FORMAT\_24 may not contain _%c_, _%Ec_, _%r_, _%R_, _%T_, _%x_, _%Ex_, _%X_, or _%EX_. * LOCALE\_YEAR\_FORMAT may not contain _%c_, _%Ec_, _%r_, _%R_, _%T_, _%x_, _%Ex_, _%X_, _%EX_, or _%Ey_. _Example._ The following file is "ja.msg", which localises the [clock] command to a Japanese locale. namespace eval ::tcl::clock { ::msgcat::mcset ja DAYS_OF_WEEK_ABBREV [list \ "\u65e5"\ "\u6708"\ "\u706b"\ "\u6c34"\ "\u6728"\ "\u91d1"\ "\u571f"] ::msgcat::mcset ja DAYS_OF_WEEK_FULL [list \ "\u65e5\u66dc\u65e5"\ "\u6708\u66dc\u65e5"\ "\u706b\u66dc\u65e5"\ "\u6c34\u66dc\u65e5"\ "\u6728\u66dc\u65e5"\ "\u91d1\u66dc\u65e5"\ "\u571f\u66dc\u65e5"] ::msgcat::mcset ja MONTHS_ABBREV [list \ "1"\ "2"\ "3"\ "4"\ "5"\ "6"\ "7"\ "8"\ "9"\ "10"\ "11"\ "12"\ ""] ::msgcat::mcset ja MONTHS_FULL [list \ "1\u6708"\ "2\u6708"\ "3\u6708"\ "4\u6708"\ "5\u6708"\ "6\u6708"\ "7\u6708"\ "8\u6708"\ "9\u6708"\ "10\u6708"\ "11\u6708"\ "12\u6708"\ ""] ::msgcat::mcset ja BCE "\u7d00\u5143\u524d" ::msgcat::mcset ja CE "\u897f\u66a6" ::msgcat::mcset ja AM "\u5348\u524d" ::msgcat::mcset ja PM "\u5348\u5f8c" ::msgcat::mcset ja DATE_FORMAT "%Y/%m/%d" ::msgcat::mcset ja TIME_FORMAT "%k:%M:%S" ::msgcat::mcset ja DATE_TIME_FORMAT "%Y/%m/%d %k:%M:%S %z" ::msgcat::mcset ja LOCALE_NUMERALS "\u3007 \u4e00 \u4e8c \u4e09 \u56db \u4e94 \u516d \u4e03 \u516b \u4e5d \u5341 \u5341\u4e00 \u5341\u4e8c \u5341\u4e09 \u5341\u56db \u5341\u4e94 \u5341\u516d \u5341\u4e03 \u5341\u516b \u5341\u4e5d \u4e8c\u5341 \u5eff\u4e00 \u5eff\u4e8c \u5eff\u4e09 \u5eff\u56db \u5eff\u4e94 \u5eff\u516d \u5eff\u4e03 \u5eff\u516b \u5eff\u4e5d \u4e09\u5341 \u5345\u4e00 \u5345\u4e8c \u5345\u4e09 \u5345\u56db \u5345\u4e94 \u5345\u516d \u5345\u4e03 \u5345\u516b \u5345\u4e5d \u56db\u5341 \u56db\u5341\u4e00 \u56db\u5341\u4e8c \u56db\u5341\u4e09 \u56db\u5341\u56db \u56db\u5341\u4e94 \u56db\u5341\u516d \u56db\u5341\u4e03 \u56db\u5341\u516b \u56db\u5341\u4e5d \u4e94\u5341 \u4e94\u5341\u4e00 \u4e94\u5341\u4e8c \u4e94\u5341\u4e09 \u4e94\u5341\u56db \u4e94\u5341\u4e94 \u4e94\u5341\u516d \u4e94\u5341\u4e03 \u4e94\u5341\u516b \u4e94\u5341\u4e5d \u516d\u5341 \u516d\u5341\u4e00 \u516d\u5341\u4e8c \u516d\u5341\u4e09 \u516d\u5341\u56db \u516d\u5341\u4e94 \u516d\u5341\u516d \u516d\u5341\u4e03 \u516d\u5341\u516b \u516d\u5341\u4e5d \u4e03\u5341 \u4e03\u5341\u4e00 \u4e03\u5341\u4e8c \u4e03\u5341\u4e09 \u4e03\u5341\u56db \u4e03\u5341\u4e94 \u4e03\u5341\u516d \u4e03\u5341\u4e03 \u4e03\u5341\u516b \u4e03\u5341\u4e5d \u516b\u5341 \u516b\u5341\u4e00 \u516b\u5341\u4e8c \u516b\u5341\u4e09 \u516b\u5341\u56db \u516b\u5341\u4e94 \u516b\u5341\u516d \u516b\u5341\u4e03 \u516b\u5341\u516b \u516b\u5341\u4e5d \u4e5d\u5341 \u4e5d\u5341\u4e00 \u4e5d\u5341\u4e8c \u4e5d\u5341\u4e09 \u4e5d\u5341\u56db \u4e5d\u5341\u4e94 \u4e5d\u5341\u516d \u4e5d\u5341\u4e03 \u4e5d\u5341\u516b \u4e5d\u5341\u4e5d" ::msgcat::mcset ja LOCALE_DATE_FORMAT "%EY\u5e74%B%Od\u65e5" ::msgcat::mcset ja LOCALE_TIME_FORMAT "%OH\u6642%OM\u5206%OS\u79d2" ::msgcat::mcset ja LOCALE_DATE_TIME_FORMAT \ "%A %EY\u5e74%B%Od\u65e5%OH\u6642%OM\u5206%OS\u79d2 %z" ::msgcat::mcset ja LOCALE_ERAS " {-9223372036854775808 \u897f\u66a6 0} {-3060979200 \u660e\u6cbb 1867} {-1812153600 \u5927\u6b63 1911} {-1357603200 \u662d\u548c 1925} {568512000 \u5e73\u6210 1987}" } In addition to the standard locales, two special locales may appear on the **-locale** parameter; **current**, which designates the result of evaluating [mclocale], and **system**, which designates the current "system" locale, which is determined by \(in order of preference\): * the date/time format settings on the Windows control panel * the environment variable LC\_TIME * the current locale from [mclocale]. ## Build System Several tools are provided for the use of maintainers: loadICU.tcl: Given a distribution of IBM's _icu4c_ <http://oss.software.ibm.com/icu/index.html> , this program analyzes the source code of the message catalogs and extracts appropriate Tcl-based messages for the date and time formats in the supported locales. loadtzif.tcl: Given a time zone information file used by the Olson version of 'tzset' \(for a description, see the latest 'tzcode' file in [ftp://elsie.nci.nih.gov/pub/]\), creates the corresponding Tcl 'tzdata' file. makeTestCases.tcl: Makes several thousand auto-generated test cases to exercise the time conversion algorithms. tclZIC.tcl: Given the source code for the Olson time zone descriptions \(obtainable as the latest 'tzdata' file in [ftp://elsie.nci.nih.gov/pub/]\), creates the full set of Tcl 'tzdata' files. Since these tools depend on third party source, they will not be included in the usual build steps; instead, maintainers will be expected to run them whenever changing files on which they depend. It will be a good practice to update the ICU and Olson files just before cutting a release. # Reference Implementation The implementation of a refactored [clock] command is a work in progress, and interested developers are urged to contact the TIP author if they want to help with implementation, documentation, or testing. The code is available in the same SourceForge repository as the Tcl core, and Tcl maintainers can obtain it with cvs -d:ext:[email protected]:/cvsroot/tcl co newclock # Notes on the cost of implementation Since it is well known that Tcl code is typically 30-50 times slower than the equivalent C, it is to be expected that [clock scan], [clock format], and [clock add] will be in that performance range. [clock seconds] and [clock clicks] will still be C code and are not expected to suffer a measurable change in performance. \(If they do, the implementors plan to address the issue.\) The cost of the time zone data files and the message catalogs is not trivial; they occupy about 1.6 megabytes exclusive of file system fragmentation and may occupy multiple megabytes depending on the minimum size of a file. The implementors assume \(and are working to ensure\) that some sort of compressed virtual file system will be available as core functionality in the 8.5 final release. With zlib compression, the message catalogs and time zone data total less than half a megabyte. It is worth noting that a distribution that must run in the absolute minimum space may omit both message catalogs and time zone data; if this is done, named time zones \(e.g., :America/New\_York\) will not be available on systems such as Windows that lack 'zoneinfo', and will suffer from Y2038 bugs on systems such as Solaris and Linux that have 'zoneinfo'. Without the message catalogs, the only supported locale will be the root locale \(and on Windows, the 'system' locale\). This combination provides functionality comparable to the [clock] command prior to this TIP. The Tcl code that implements [clock] is less than eighty kilobytes with comments and blank lines removed; this amount of overhead is thought to be negligible. # Bugs The reference implementation does not attempt any calendars not based on the hybrid Julian/Gregorian calendar. This implementation is adequate for the Western countries and for the Japanese civil calendar, but does not address the Hijri, Hebraic, Thai, Chinese or Korean calendars. \(No Tcl user has requested these, to the best of the knowledge of the author of this TIP.\) The Gregorian change date is not supplied in most locales. Localisation in most locales was done by an American who is probably excessively ignorant in such matters. This TIP makes no effort to be compliant with RFC 2550 <http://www.faqs.org/rfcs/rfc2550.html> . # Copyright Copyright 2004, by Kevin B. Kenny. Redistribution permitted under the terms of the Open Publication License <http://www.opencontent.org/openpub/> . # Acknowledgments The author of this TIP wishes to thank all the Tcl'ers who have taken the time to read and comment on it, most notably Joe English, Donal K. Fellows, Jeff Hobbs, Arjen Markus, Reinhard Max, Christopher Nelson, Donald G. Porter, Pascal Scheffers, and Peter da Silva. |
Name change from tip/174.tip to tip/174.md.
|
| < | < | | | | | | | | | | | > | | | | | | | | | | | | | < > | < | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 174: Math Operators as Commands Author: Kristoffer Lawson <[email protected]> Author: Donal K. Fellows <[email protected]> Author: David S. Cargo <[email protected]> Author: Peter Spjuth <[email protected]> Author: Kevin B. Kenny <[email protected]> State: Final Type: Project Vote: Done Created: 15-Mar-2004 Post-History: Tcl-Version: 8.5 ----- # Abstract This TIP describes a proposal for math operators in Tcl as separate commands, acting much like the equivalent in the Lisp language. This would make simple usage of mathematics much clearer. # Rationale While the **expr** command works fairly well for longer mathematical expressions, it is extremely tedious for the most common uses, such as handling indices. Take the following examples: set newList [lrange $list [expr {$idx - 5}] [expr {$idx + 5}]] .c create oval [expr {$x - $r}] [expr {$y - $r}] [expr {$x + $r}] [expr {$y + $r}] Many find this particular aspect of Tcl unappealing. It gets increasingly difficult to read as more and more simple mathematical expressions build up. \(See _Example_ below for how these will look after the proposed change.\) # Proposed Change 1. A group of Tcl commands are added which would handle mathematical operations without the need to use **expr**. Most commands would take a variable amount of arguments and would work such that the operator is applied to the combination of the first and second arguments. The result of this combination is then used with the operator for the third argument, etc. If only one argument is given, it is returned as is. See below for details for each operator. An example implementation of the **\+** command in Tcl follows: proc ::tcl::mathop::+ {args} { set r 0 foreach operand $args { set r [expr {$r + $operand}] } return $r } 2. All operator commands will be kept in the **::tcl::mathop** \(in line with _::tcl::mathfunc_ from [[232]](232.md)\) namespace, from which they would most commonly be imported into the calling namespace \(or resolved in it by means of the **namespace path** \([[229]](229.md)\) command\). 3. The commands are not connected to their corresponding **expr** operator. Overloading or adding any command in **::tcl::mathop** does _not_ affect operators in **expr** or any other command that calls _Tcl\_ExprObj_, and nor does overriding **expr** alter the behaviour of any command in **:::tcl::mathop**. ## Operator Commands Details Unary operators **~** and **!** always take one argument. Op/argc 0 1 2 3+ ~ err ~a err err ! err !a err err Left-associative operators that naturally allow 0 or more arguments do so: Op/argc 0 1 2 3+ + 0 a a+b a+b+c... * 1 a a*b a*b*c... & -1 a a&b a&b&c... ^ 0 a a^b a^b^c... | 0 a a|b a|b|c... Other left or right associative operators. Operator **\*\*** is right associative, which needs to be noted clearly. Op/argc 0 1 2 3+ ** 1 a a**b a**(b**(c...)) \(This behaviour depends on the eventual modification of the **\*\*** operator in [expr] to have right-associativity, which is the subject of [[274]](274.md). If TIP \#274 fails, **\*\*** should be left- or non-associative.\) Nonassociative operators \(including the list operators, "**in**" and "**ni**"\) must always be binary. Op/argc 0 1 2 3+ << err err a<<b err >> err err a>>b err % err err a%b err != err err a!=b err ne err err a ne b err in err err a in b err ni err err a ni b err Subtract and divide treat their arguments in a left-associative way _except_ for in the unary case. Unary minus is negation, and unary divide is reciprocal. Op/argc 0 1 2 3- - err -a a-b ((a-b)-c)... / err 1.0/a a/b ((a/b)/c)... Comparison operators other than **!=** and **ne** test for ordering: Op/argc 0 1 2 3+ < 1 1 a<b ((a<b)&(b<c)&...) <= 1 1 a<=b ((a<=b)&(b<=c)&...) > 1 1 a>b ((a>b)&(b>c)&...) >= 1 1 a>=b ((a>=b)&(b>=c)&...) == 1 1 a==b ((a==b)&(b==c)&...) eq 1 1 a eq b ((a eq b)&(b eq c)&...) \(Note the single **&**; a Tcl command is not capable of "short circuit" evaluation of its arguments.\) The operators that do conditional evaluation of their arguments \(&&, \|\| and ?:\) are not included. This is because their characteristic evaluation laziness is best modelled using the existing **if** command. ## Example As an example use, let us change the lines from above: set newList [lrange $list [- $idx 5] [+ $idx 5]] .c create oval [- $x $r] [- $y $r] [+ $x $r] [+ $y $r] This is clearly shorter and much easier on the eyes. There is no need to consider the effects of bracing expressions. Sum of a list becomes set sum [+ {expand}$list] # Security considerations It is worth noting that variadic operators have no way of "short circuit" evaluation, much as putative **&&** and **\|\|** commands would not. This consideration means that they must be used with caution in cases where expressions have side effects; all their arguments will be evaluated. Commands like < 1 0 [don't do this!] / 0 0 [don't do this!] will indeed evaluate the string in square brackets. If expressions like these are constructed from user input, care must be taken to place them in a safe execution environment or otherwise defend against code injection attacks. \(This last consideration is somewhat far-fetched, since it is implausible that an injection attack would be able to generate [< 1 0 [don't do this!]] but not [< [don't do this!] 0].\) # Implementation ## Efficiency These commands can naturally be compiled and thus as efficient as their corresponding **expr** operators. The following lines should probably result in the same byte codes. set x [expr {$a * $b + $c}] set x [+ [* $a $b] $c] ## Reference Implementation Available online at SourceForge <http://sf.net/tracker/?func=detail&aid=1578137&group_id=10894&atid=310894> . The patch is for this TIP as it stood several versions ago; in particular, it does not implement the ordering comparators and gets associativity wrong in a couple of other cases. Nevertheless, the authors of this TIP believe it to be an adequate proof that the ideas of the TIP are implementable with good performance. # Copyright This document has been placed in the public domain. |
Name change from tip/175.tip to tip/175.md.
|
| < | < | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 175: Add an -async Option to [open] Author: Neil Madden <[email protected]> State: Withdrawn Type: Project Vote: Pending Created: 15-Mar-2004 Post-History: Tcl-Version: 9.0 ----- # Abstract This TIP propose to add an _-async_ option to the [open] command, with identical semantics to the _-async_ option to the [socket] command. # Rationale With the introduction of Virtual File Systems \(VFS, see [[17]](17.md)\), it is now possible to use [open] to access resources which are not available in the local file system. However, initial access to these resources may take some time \(for instance, in an HTTP VFS, this requires an HTTP GET request to a remote server\). Currently, while this request is being processed, the Tcl application will block waiting for a response. It may take several seconds before the open call returns, and control is passed back to the application. Delays of this length can cause problems, especially in applications with a Tk graphical user interface, which will not repond to events until the call has completed. Tcl provides mechanisms to avoid this initial blocking for the socket command, and in the HTTP package. However, this functionality is missing from the open command. For VFS to become useful for writing network code, this functionality needs to be added. # Proposed Change This TIP proposes adding an _-async_ option to the open command. The new syntax for the open command would be: open ?-async? ?--? name ?access? ?permissions? The "--" marker is also proposed to signify "end of options". This is needed as _name_ can be anything, including the string "-async", and so some mechanism is needed to distinguish between the _-async_ option, and the name. This is in line with other commands which take multiple options. When the _-async_ option is present, the open command will return immediately, without waiting for the underlying channel to be created and connected. If the channel is configured for blocking mode, a _gets_ or _flush_ that is done on the channel before the connection is made will wait until the connection is completed, or fails. If the channel is configured for nonblocking mode, then a _gets_ or _flush_ on the channel before the connection has been made will return immediately and _fblocked_ on the channel will return 1. This is exactly the same behaviour of the current implementation of the _-async_ option to the _socket_ command. In addition, each VFS should support the _-error_ option to _fconfigure_ to allow scripts to determine the cause of an error when asynchronous opening fails. Furthermore, there needs to be a mechanism for notifying a script when an asynchronous open fails. This could be achieved by firing any fileevents \(readable or writeable\) which are registered on the resulting channel. This is the behaviour of [socket -async]. In order for this TIP to be implemented, there would have to be changes to the VFS layer in Tcl. There are at three ways to accomplish this: 1. Extend Tcl\_FSOpenFileChannelProc to accept an _async_ argument, of type _int_. 2. Extend the Tcl\_Filesystem structure to add a new callback, alongside T\_FSOFCP. For instance, Tcl\_FSOpenFileChannelAsyncProc. 3. \(Ab\)use the _mode_ parameter, and add a mask such as TCL\_ASYNC. Of these, option 3 is the easiest in terms of maintaining compatibility, but is not the nicest implementation. # Reference Implementation A reference implementation does _not_ yet exist. The TIP author would be willing to implement any changes needed, but currently is not familiar with the internal workings of the VFS system. # Questions Should the _-async_ option be supported when a command pipeline is being created? Should a more general option passing mechanism be implemented? It is possible that some VFS implementations may require more information than is currently available in order to correctly create a channel \(the _-myaddr_ and _-myport_ options to socket spring to mind\). Would it be more sensible to consider a proposal for a more general option passing mechanism, to avoid further updates to the API in the future? This TIP does _not_ propose such a mechanism. # Copyright This document has been placed in the public domain. |
Name change from tip/176.tip to tip/176.md.
|
| < | < | | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 176: Add String Index Values Author: Damon Courtney <[email protected]> Author: Don Porter <[email protected]> Author: Damon Courtney <[email protected]> State: Final Type: Project Vote: Done Created: 16-Mar-2004 Post-History: Tcl-Version: 8.5 ----- # Abstract This TIP proposes extended index formats to be recognized by **TclGetIntForIndex**, supporting simple index arithmetic for string and list indices. # Rationale Most of Tcl's commands that accept an integer index of some kind also accept a string index in the format of _end-N_. This is an extremely useful feature which I hope to extend just slightly by allowing simple addition to the standard index forms to be done during index processing. The change is mostly just syntactic sugar, but it extends a functionality that is already there and does not change any other syntax. The aim of the proposal is to allow shorthand list and string operations like so: set x [lsearch $list $elem] set new [lrange $list $x-1 $x+1] set x [string first $string "foo"] set new [string range $string $x $x+5] # Proposal The description of the supported index formats documented for the **string index** command will be updated to read: * _integer_ > \* For any index value that passes **string is integer -strict**, the char specified at this integral index \(e.g. **2** would refer to the **c** in **abcd**\). * end > \* The last char of the string \(e.g. **end** would refer to the **d** in **abcd**\). * end-_N_ > \* The last char of the string minus the specified integer offset _N_ \(e.g. **end-1** would refer to the **c** in **abcd**\). * end\+_N_ > \* The last char of the string plus the specified integer offset _N_ \(e.g. **end\+-1** would refer to the **c** in **abcd**\). * _M_\+_N_ > \* The char specified at the integral index that is the sum of integer values _M_ and _N_ \(e.g. **1\+1** would refer to the **c** in **abcd**\). * _M_-_N_ > \* The char specified at the integral index that is the difference of integer values _M_ and _N_ \(e.g. **2-1** would refer to the **b** in **abcd**\). * In the specifications above, the integer value _M_ contains no trailing whitespace and the integer value _N_ contains no leading whitespace. The internal routine **TclGetIntForIndex** will be updated to implement the parsing specified by the documentation above. The documentation of all Tcl commands that call **TclGetIntForIndex** to parse index values will be updated to refer to the documentation for **string index** for a description of the index format. These commands include **lindex**, **linsert**, **lrange**, **lreplace**, **lsearch**, **lset**, **lsort**, and **string**. This documentation update will remove any mention that the index values **e** and **en** are supported \(as prefixes of **end**\). Their support will be continued for compatibility, but that support will now be undocumented and deprecated. The implementation of the commands **regexp -start** and **regsub -start** will be updated to call **TclGetIntForIndex** so that the full set of index formats will be supported. \(Currently only integer values are accepted\). The error message produced by **TclGetIntForIndex** when parsing an invalid index will be updated to give the advice **must be integer?[+-]integer? or end?[+-]integer?**, in agreement with the extended set of index formats. # Implementation Tcl Patch 1165695 is a draft implementation. It accomplishes everything proposed above except the update to the error message. If this proposal is accepted, that change, plus the large number of test suite updates it would require, will be added. Tests of the new functionality are also still to come. # Compatibility Support for the index format end-_N_ where _N_ is an integer with leading whitespace is removed by this proposal. For example the string **end- 1** will no longer be recognized as a valid index. Most programmers are surprised to learn that this format is supported currently, so this incompatibility is not expected to cause much of a problem. # Discussion Summary This feature is added as a quick, simple convenience to having to always use a full-blown expression for a minor task. It was briefly discussed that since indexes already allowed a space between the - and the N we should continue to support this, but it makes the implementation harder, and no one seemed to care that much. The fact that it breaks backwards compatibility is a small issue since no one seems to use indexes in this manner anyway. The idea of making indexes extend a list beyond its length by doing something like [linsert $list end+10 $elem] was discussed but tabled since it is much harder to implement and is really outside the scope of this TIP. This may be something to discuss for a future TIP though. # Copyright This document has been placed in the public domain. |
Name change from tip/177.tip to tip/177.md.
|
| < | | | | | | < | | | > | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 177: Add -stretch Option to panedwindow Widget State: Final Type: Project Tcl-Version: 8.5 Vote: Done Post-History: Author: Brian Griffin <[email protected]> Created: 17-Mar-2004 Keywords: Tk ----- # Abstract This TIP proposes adding a **paneconfigure** option to **panedwindow**s that will allow alternative fill behavior. # Rationale The current behavior, although reasonable, is too limiting. We should give control to programmers so that they can specify the fill behavior in a way that makes sense for their application. # Proposed Change Currently, the **panedwindow** widget gives any remaining space \(or takes away space\) from the last \(right most or bottom most\) pane only. This proposal will add a per pane configure option so that any or all panes may receive the additional space. A **-stretch** option will be added to the paneconfigure list of options. The value will be an enumeration of "**last**", "**first**", "**middle**", "**always**", and "**never**". The default value will be "**last**" which maintains the **panedwindow**'s current behavior. The **panedwindow** will calculate the required size of all its panes. Any remaining \(or deficit\) space will be distributed to those panes marked for stretching. The space will be distributed based on each panes current ratio of the whole. For example, given panes _a_, _b_, and _c_, where only _b_ and _c_ are marked for stretching and _b_ is 25% of the size of \(_b_\+_c_\), then _b_ will receive 25% of the surplus or deficit space. The **-stretch** enumeration values have the following meaning: last: Only if this pane is the last \(right-most or bottom-most, depending on overall orientation\) pane will it stretch. first: Only if this pane is the first \(left-most or top-most, depending on overall orientation\) pane will it be stretch. middle: Only if this pane is _not_ the first or last pane will it stretch. always: This pane will always stretch. never: This pane will never stretch. # Draft Implmentation An implementation of this enhancement is availble [ftp://ftp.model.com/pub/tcl/pw_stretch_TIP.tgz]. # Copyright This document has been placed in the public domain. |
Name change from tip/178.tip to tip/178.md.
|
| < | < | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 178: [info pid] and [info tid] Subcommands Author: Joe Mistachkin <[email protected]> State: Draft Type: Project Vote: Pending Created: 21-Mar-2004 Post-History: Tcl-Version: 8.7 ----- # Abstract This TIP proposes two new **info** subcommands which are used to obtain the current process and thread identifiers. # Rationale In certain types of applications, it is important to know what thread is currently executing. This is especially true for multithreaded applications or for scripts running in a threaded build of Tcl. While the author realizes that there is already a **pid** command, the addition of the **info pid** subcommand still makes sense for the following reasons: * The **pid** command can also provide information totally unrelated to the _current_ process identifier. At one point \([[88]](88.md)\) it was even suggested that the **pid** command be overloaded to provide process control related functionality. * To allow scripts that dynamically build other scripts \(potentially for use with safe interpreters\) using the **info** command and caller provided arguments. Using the **info** command instead of the **pid** command limits the amount of information that can be obtained by the safe interpreter. * It is the opinion of the author that _informational_ commands, such as **pid** should really be subcommands of **info** as we start to move forward with the development of Tcl. # Justification The **info tid** command should be in the core because the identity of the currently executing thread is just as fundamental on all modern operating systems as the current process identity. Once the thread identity is known, it can be used to communicate with other processes and threads in useful ways that do not require the Thread package. Loading the entire Thread package just to get the identity of the currently executing thread is overkill and may not be a good solution in application embedding scenarios. This is especially true for the browser plugin where loading extra packages is not ideal. # Proposed Change Two new subcommands, **info pid** and **info tid**, would be added to the **info** command with the following syntax: > **info pid** This subcommand would return the process identifier for the current process. > **info tid** This subcommand would return the thread identifier for the current thread. # Draft Implmentation A complete implementation of this TIP is available <http://sf.net/tracker/?func=detail&aid=920731&group_id=10894&atid=310894> . # Copyright This document has been placed in the public domain. |
Name change from tip/179.tip to tip/179.md.
|
| < | | | | | | < | | | > | | | | | | | | | | | | | | | | | > | 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 | # TIP 179: Add -hide Option to panedwindow Widget State: Final Type: Project Tcl-Version: 8.5 Vote: Done Post-History: Author: Brian Griffin <[email protected]> Created: 22-Mar-2004 Keywords: Tk ----- # Abstract This TIP proposes adding a **paneconfigure** option to **panedwindow**s that will control pane visibility. # Rationale Adding control over individual pane visibility to the **panedwindow** widget would simplify the construction and control of complex user interfaces. For example, look at applications such as Komodo, or MS Visual Studio, where the U/I contains 4-7 panes in 2 or more nested panedwindows. Both of these applications as well as many others allow user controlled visibility of individual panes. Trying to manage the visibility and placement of these panes requires much additional code and adds complexity to the U/I implementation. Alternatively, if the panedwindow allowed control of visibility while maintaining pane position and configure options \(as does the **grid remove** method\), the U/I code is essentially reduced to a simple one line [_$w_ **configure -hide**]. # Proposed Change This TIP will add a **-hide** option to the **paneconfigure** for individual panes. The option will control the visibility of the pane. When set to true \(as interpreted by _Tcl\_GetBooleanFromObj\(\)_\), the pane will be unmapped and will not be considered when arranging the remaining panes for display. Hidden panes will still be reported by the [_$w_ **panes**] method and can be referenced when adding panes with the **-after** or **-before** options. The advantage of a **paneconfigure** option over the **remove** method of the **grid** command is that the pane is still query-able and configurable. # Draft Implementation An implementation of this enhancement is available [ftp://ftp.model.com/pub/tcl/pw_hide_TIP.tgz]. # Copyright This document has been placed in the public domain. |
Name change from tip/18.tip to tip/18.md.
|
| < | < | | | | | | | > | | | | | 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 | # TIP 18: Add Labels to Frames Author: Peter Spjuth <[email protected]> State: Final Type: Project Vote: Done Created: 12-Dec-2000 Post-History: Tcl-Version: 8.4 ----- # Abstract This TIP proposes to add a labelled frame widget to Tk. # Introduction Labelled frames are a common thing in a GUI and the need for them are rather clear by the fact that practically every widget package implements some version of it. This proposal wants to add simple labelled frames to Tk. Even though a labelled frame can be built by three frames and label, this requires some skill and a bit work. I believe such a basic thing should be easier and this change would make creating a labelled frame as simple as it deserves to be. Below is an example of what I mean with a labelled frame. ![Example of labelled frame](../assets/18labframe.png) # Specification A new widget class, labelframe, is added. It works like a frame, with the following changes. These options are added: -text: Standard option. Default value "". |
︙ | ︙ | |||
60 61 62 63 64 65 66 | -borderwidth, new default value 2. -relief, new default value groove. -padx and -pady are useful in frames and toplevels too, and since it is easy and cheap to add them at the same time, this TIP proposes to add them there too. | | | | | | | | | | | | | | | | | | 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 | -borderwidth, new default value 2. -relief, new default value groove. -padx and -pady are useful in frames and toplevels too, and since it is easy and cheap to add them at the same time, this TIP proposes to add them there too. # Rationale My main approach has been to make a simple but still general solution. The most typical usage should be really easy, more advanced usage possible, and more features should be possible to add later if needed. Trying to mimic all the abilities of a label widget is rather futile. It leads to code duplication and future updates to the label widget would need to be copied too to keep up. Since the most common label is a simple text, the labelframe only mimics options -text, -font and -fg to be able to handle that case in a simple manner. If you want a more advanced label, e.g. with an image or with a checkbutton, you can get it with -labelwidget. For placement of the label I chose a style I found in IWidget's "labeledframe" widget. It's the most general solution I can see since it allows access to all twelve obvious positions in an easy way. Options -padx and -pady does not have anything directly to do with labels, but are a generally nice addition to frames that I have missed a lot in the past. Such padding is not possible without part of the changes to geometry management \(see Implementing section\) that are required for displaying the label. The thing about raising the -labelwidget in the stacking order comes from this: With the most simple implementation, using -labelwidget could be done in two ways: # Way #1 labelframe .f label .f.l -text Mupp .f configure -labelwidget .f.l # Way #2 label .l -text Mupp labelframe .f -labelwidget .l raise .l .f In the first you want the label to be a child but since it has to exist, the -labelwidget can't be used on the labelframe creation line. In the second you try to circumvent it by creating the label first, but then you have to raise it above the labelframe to be visible. Even though it's just one extra line of code I find it a bit awkward when it's so easy to do something about. The first can be fixed by not trying to do anything with the label widget until idle time when it has had a chance to be created. This is not a good solution though since it leads to some rather awkward things in implementation. The second can be fixed by automatically raising the label in the stacking order when used as -labelwidget. If this is documented clearly I don't have a problem with it, and that is why I chose it. # Alternatives to this TIP An alternative way to implement a labelled frame is using mega widget style with a subframe where children are placed. This is how current widget packages do it. I think that is an awkward and unnatural way to handle such a simple thing as a labelled frame. The only reason to do so is that current limitations in geometry management prevents a simpler solution. I believe that a labelled frame should work like a normal frame. That it displays a label should not matter more than displaying a border or a blue background. A labelled frame megawidget would be different from a frame, the most noticeable difference being that you can't pack/grid things directly into the labelled frame, instead you have to go via a subframe. Having the labelled frame work like a normal frame is more consistent and easier for the programmer at Tcl level. # Implementing Implementing this is mostly rather straightforward. The labelframe will share most code with the frame, just like toplevel and frame share code today, and like the spinbox was built on the entry. The tricky part is that limitations in geometry management does not leave room for displaying a label. The changes needed in geometry management are simple but introduces a slight backward incompatibility. The problem is this. Today a widget can set an internal border width. This defines a uniform width area around the edge of the widget that geometry managers should stay away from. This is not enough though, since to display a label the frame needs to get more space on one side where it will put the label. Also, there is no way for a widget to affect its own size \(anything it says is overridden by pack/grid\), so the labelframe cannot make sure that enough size is requested to make room for the label. By adding some more fields to the TkWindow structure, the information needed can be transferred to the geometry manager. First, the present internalBorderWidth field is split into four fields, one for each side. Second, minimum requested width/height fields are added. This requires one macro per field for reading them and two new APIs to set the fields: void Tk_SetInternalBorderWidthEx(tkwin, left, right, top, bottom) void Tk_SetMinimumRequestedSize(tkwin, minWidth, minHeight) Geometry managers would need to be updated to take the new fields into consideration, and here is where backwards compatibility comes in. Any extension implementing a geometry manager would need to be updated in the same way as grid/pack/place will be. The change is trivial, and even if not done most things will work anyway. An updated Tk plus an old extension plus an old script will still work and thus no one needs to worry about upgrading. I consider this a minor thing since it wont break any existing applications. The only thing that will break is if someone would try to use a geometry manager that is not updated within a labelframe. And even in that case you can work around it with an extra frame. # Rejected alternatives The ability to display a label could have been given to the normal frame by adding the options above to it. Having a new widget class has the following advantages: The separate widget class can have its own default values, and the user can control it separately from the frame in the option database. |
︙ | ︙ | |||
206 207 208 209 210 211 212 | 1.1 of this TIP has also been discarded because it was too complex. It would be possible to do without the minimum requested size fields if you give the responsibility to make sure the label has room to the GUI programmer. This could be rather awkward though, e.g. when making an internationalized application where labels can vary a lot. | | | | > | 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 | 1.1 of this TIP has also been discarded because it was too complex. It would be possible to do without the minimum requested size fields if you give the responsibility to make sure the label has room to the GUI programmer. This could be rather awkward though, e.g. when making an internationalized application where labels can vary a lot. # Reference Implementation An almost finished implementation exists, and it's just a matter of polishing the last bits to create a patch for this proposal if it is accepted. At <http://www.dtek.chalmers.se/~d1peter/labframe.tcl> you can find a pure Tcl demo of labelled frames. Even though it uses sub-frames and thus do not live up to what I want to accomplish here it implements all new options as specified here and can be played with if you want to know more. # Copyright This document has been placed in the public domain. |
Name change from tip/180.tip to tip/180.md.
|
| < | | | | < | | | | | > | | | | 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 | # TIP 180: Add a Megawidget Support Core Package Author: Damon Courtney <[email protected]> Tcl-Version: 8.7 Created: 22-Mar-2003 Type: Project State: Draft Vote: Pending Post-History: Keywords: Tk ----- # Abstract This TIP proposes the addition of a "megawidget" package to Tk as a core package which contains a set of functions useful for building megawidgets with standard script-level behaviour in Tk. # Rationale It's obvious \(to me at least\) from the \(growing\) number of pure-Tcl megawidget packages that it would be very helpful for Tk to provide some mechanism to help all these various packages do things in some standard way. For example, there is a base set of options and commands that are supported by all Tk core widgets that should also be supported in any megawidget. Now, most of the packages do their job at supporting |
︙ | ︙ | |||
38 39 40 41 42 43 44 | mostly meant for the developer's developer. This TIP does not seek to tell megawidget extension writers how they should write their widgets. Eveyone has their own ideas of how that should be done. This package merely provides some helper functions to try and speed up the most common widget functions. | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | mostly meant for the developer's developer. This TIP does not seek to tell megawidget extension writers how they should write their widgets. Eveyone has their own ideas of how that should be done. This package merely provides some helper functions to try and speed up the most common widget functions. # Specification The commands for this package are all written in C for speed reasons. After testing different megawidget packages, I find that most of them are very slow at the most basic widget functions like **cget** and **configure**. That was why I set out to write all of the standard functions in C and provide the hooks for various packages to use them instead of all the homegrown solutions that have been used. The following commands would be part of the package: **::megawidget::class** _widgetClass_ > Define a new megawidget class. **::megawidget::commands** _widgetClass_ ?_command ..._? > Define a list of subcommands available to widgets of _widgetClass_. **::megawidget::options** _widgetClass_ ?_optionList ..._? > Define the options available to widgets of _widgetClass_. An _optionList_ is a list describing the option: > _type option dbClass dbName defValue_ > The _type_ value can be **boolean**, **int**, **double**, **string**, **enum**, **color**, **font**, **bitmap**, **border**, **relief**, **cursor**, **justify**, **anchor**, **synonym**, **pixels**, or **window**. The other values should be familiar to users of Tk's standard **configure** subcommand. **::megawidget::create** _widgetName widgetClass commandName_ > Create a new megawidget of class _widgetClass_ from _widgetName_. _widgetName_ must already exist as a widget, and its widget command will be renamed to _commandName_ and replaced by a new command that will handle the defined subcommands for the widget class. **::megawidget::cget** _pathName option_ > Get the value of a megawidget option for _pathName_. This function is also called as a result of [_pathName_ **cget**]. **::megawidget::configure** _pathName_ ?_option_? ?_value option value ..._? > Configure or query option values for the megawidget _pathName_. This function is also called as a result of [_pathName_ **configure**]. The options of a widget are stored and retrieved in dictionaries. The **configure** and **cget** commands are handled by the widget command after a widget is created, and all other commands are passed to the author to handle. Some options \(like **-cursor**, **-background**, **-borderwidth**, **-bg**, **-bd**\) should probably be created for all megawidgets, but that has yet to be decided and is open for discussion. # Author's Note I have completed work on this package with all the functions written in C and with great care to keep them as fast and efficient as possible. Porting the BWidget ButtonBox to SNIT and doing some test is what got me to this point. I was simply trying to create a widget and do a **cget**. The results were pretty disappointing considering the very basic **cget** command. Native Tk widget: 2 microseconds BWidget widget: 60 microseconds SNIT widget: 260 microseconds With **::megawidget::cget**, I get around 4 microseconds, which is pretty close to native Tk widgets. # Copyright This document has been placed in the public domain. |
Name change from tip/181.tip to tip/181.md.
|
| < | < | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 181: Add a [namespace unknown] Command Author: Neil Madden <[email protected]> State: Final Type: Project Vote: Done Created: 23-Mar-2004 Post-History: Tcl-Version: 8.5 ----- # Abstract This TIP proposing adding a new **namespace** subcommand, **unknown**, which would register a per-namespace procedure for dealing with unknown commands. # Rationale There is an occassional need within Tcl scripts to change the way in which command names are resolved, for instance when implementing language constructs such as object systems or lexically-scoped commands. Many of these issues are addressed by the newly-accepted **namespace path** command [[229]](229.md). However, there are still a few situations where more customized behaviour is required. For instance, implementing custom per-namespace command auto-loading, or to use auto-expansion of leading word as in TOOT <http://wiki.tcl.tk/11543> . Currently, the only way to perform such customized command resolution behaviour is to override the global **::unknown** proc to install your custom handler. There are several drawbacks with this mechanism. Firstly, it is difficult to override the global **::unknown** proc if you are writing a package, as good style dictates that you shouldn't override commands outside your package namespace without being explicitly asked to do so. Secondly, as Tcl searches for a hard-coded fallback procedure name \(**::unknown**\), in order to override it's functionality you have to rename it and then install your own replacement - and the new version becomes the default fallback behaviour for the entire application. In the case of implementing custom auto-loading behaviour, you may only want to override the behaviour for your namespace, and not for the entire interpreter. Currently, the only way to do this is to define a new **::unknown** procedure which does pattern matching on the command name it is passed. Finally, if a package does override the **::unknown** procedure it has to be careful to save the old handler, and then invoke it for commands which it is not interested in. This is an error-prone approach, and results in a cascade of procedure calls, often with each one only interested in a subset of the commands being searched for. # Related TIPs There have been two previous attempts at modifying Tcl's command resolution process. [[52]](52.md) proposed that the search order be changed to traverse the complete namespace hierachy from most specific namespace to the most general \(the global namespace\). This TIP was withdrawn as it was not backwards compatible. [[142]](142.md) proposed a global variable which would hold a namespace search path. This TIP was also withdrawn as it does not allow different namespaces to have different search paths. [[229]](229.md) proposed the **namespace path** command as a way of specifying a per-namespace search path for command resolution. This TIP was accepted, and provides a good general mechanism for custom command resolution. The current TIP is complementary to [[229]](229.md) and can be used to handle cases where more flexible behaviour is required. # Proposed Change This TIP proposes that the handling of unknown commands be done on a per-namespace basis through the introduction of an **unknown** subcommand of the **namespace** command. > **namespace unknown** ?_commandPrefix_? The subcommand would accept either zero or one argument\(s\), and is similar in interface to the **interp bgerror** command added by [[221]](221.md). If no arguments are given, the command returns the handler for the current namespace. The optional argument _commandPrefix_ is a command \(strictly a prefix list consisting of a command and optional arguments\) to execute if normal command lookup from the current namespace fails. The command will be concatenated with the full invocation line of the command being searched for \(i.e. the command name and all arguments\), and evaluated in the scope of the current namespace. The first word in the list given must be a command name which must be able to be resolved without resorting to the unknown mechanism \(i.e. it must either be a command in the current or global namespace, or be fully-qualified\). If this cannot be done, a stock error message will be generated referring to the original unknown command \(and _not_ the missing handler\) - this is how Tcl currently behaves if no **::unknown** procedure exists. The command resolution procedure would be altered from this: 1. Lookup command in current namespace. 2. If that fails, use path supplied by **namespace path**. 3. If that fails, lookup command in global namespace. 4. If that fails, call global **::unknown** procedure. to this: 1. Lookup command in current namespace. 2. If that fails, use path supplied by **namespace path**. 3. If that fails, lookup command in global namespace. 4. If that fails, call the unknown handler for the namespace in which the unknown command was invoked. Note that this TIP does not change \(or allow changing\) the default command resolution procedure - the current, namespace path, and global namespaces are always searched before the unknown handler is called. This is so that resolution of the unknown handler itself can be performed, and so that the handler can be implemented without resorting to fully qualifying every command in it \(e.g. having to use ::set\). It also should be noted that the unknown handler that is called is for the namespace that _invoked_ the unknown command, rather than the namespace which is the _target_ of the call. There are a number of reasons for this decision: Firstly, there is no guarantee that the target namespace actually exists \(this might be a reason why the command was not found\). In that case, there would be no target namespace unknown handler, and we would be forced to fallback on the global default. Secondly, the mechanism is designed mainly for namespace authors who wish to implement some custom behaviour that affects the operation of their own code, e.g., custom auto-loading of missing commands, or more sophisticated command lookup procedures, etc. This suggests that the responsibility for dealing with unknown commands should fall on the originating namespace, rather than being placed on arbitrary other namespaces. It is believed that this is the most sensible, and the most predictable, behaviour for an unknown command mechanism. In addition, with the introduction of **namespace ensemble** [[112]](112.md) there now exists a flexible mechanism for handling the opposite behaviour, allowing the target namespace to handle requests for unknown commands \(e.g., forwarding requests\). The author of the present TIP considers this to be the right division of responsibility, as ensembles should become the default mechanism for accessing public operations of external namespaces, and also an ensemble command can be guaranteed that the target namespace does indeed exist. The default unknown handler for the global namespace is a handler called **::unknown**. The default handler for other namespaces calls the global unknown handler. This means that by default, we have exactly the same mechanism that exists currently in Tcl. In order to change the mechanism for an individual namespace, you may register a new unknown handler for that namespace. When no handler is registered for a namespace, then a call to **namespace unknown** will return an empty string \(for non-global namespaces\) or **::unknown** for the global namespace. This is so that a distinction can be made between namespaces which have no handler set, and namespaces which have had an unknown handler called **::unknown** deliberately registered for them. With this scheme it is possible to set a global per-interpreter unknown command handler by setting the unknown handler for the global namespace. This can then be overridden on a per-namespace basis, if required. The calling of unknown handlers registered with **namespace unknown** would be identical to the current calling of the **::unknown** procedure - the handler will be called with the command name and all of its arguments, as it was originally invoked. The handler should be a valid Tcl list representing a command and possible initial arguments. For instance, a single handler proc could be used for several namespaces with the namespace passed as an argument: proc handleunknown {ns cmd args} { ... } namespace eval foo { namespace unknown [list ::handleunknown ::foo] } namespace eval bar { namespace unknown [list ::handleunknown ::bar] } Setting the unknown handler to \{\} \(an empty list\) restores the default handler \(**::unknown** for global namespace, global unknown handler for all other namespaces\). ## C API Additionally, this TIP proposes adding two new public functions to the Tcl C-API to expose this functionality at the C-level. The proposed new functions are: Tcl_Obj *Tcl_GetNamespaceUnknownHandler(Tcl_Interp *interp, Tcl_Namespace *nsPtr); Returns the current unknown command handler registered for the given namespace, or NULL if none is. int Tcl_SetNamespaceUnknownHandler(Tcl_Interp *interp, Tcl_Namespace *nsPtr, Tcl_Obj *handlerPtr); Sets the unknown command handler for the namespace, or resets it to the default if _handlerPtr_ is NULL or an empty list. ## Consequences As a final note, there is a useful side-effect to always resolving the unknown handler itself in the current namespace, in that an unknown handler can be registered for the global namespace which is not fully qualified, and it will be resolved relative to the namespace in which an unknown command is invoked. To illustrate: # Set global unknown handler to unqualified name namespace unknown unknown namespace eval foo { proc unknown {args} { puts "FOO" } } proc unknown {args} { puts "GLOBAL" } bar ;# prints GLOBAL namespace eval foo { bar } ;# prints FOO namespace eval other { bar } ;# prints GLOBAL # Reference Implementation A reference implementation is available attached to Patch 958222 on the Tcl project at SourceForge <http://sf.net/tracker/?func=detail&aid=958222&group_id=10894&atid=310894> . The current patch is called tip181-4.patch # Copyright This document has been placed in the public domain. |
Name change from tip/182.tip to tip/182.md.
|
| < | < | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 182: Add [expr bool] Math Function Author: Joe Mistachkin <[email protected]> Author: Don Porter <[email protected]> State: Final Type: Project Vote: Done Created: 23-Mar-2004 Post-History: Tcl-Version: 8.5 ----- # Abstract This TIP proposes a new **expr** math function **bool\(\)**. # Background Several of the Tcl/Tk built-in commands make use of the notion of a Boolean value, a value that can be either true or false. Boolean values show up in control commands like **if** and **while**, and they also are used to enable/disable certain features, as in **tcltest::singleProcess $bool** and **namespace ensemble configure $ens -prefixes $bool**. There have long been two distinct notions of the set of string values that are recognized as boolean values. The **Tcl\_GetBoolean\(\)** routine recognizes the following strings and their unique prefixes, in all case variations, and _nothing else_ as valid boolean values: **0**, **1**, **yes**, **no**, **true**, **false**, **on**, **off**. Several script-level commands are implemented by calls to **Tcl\_GetBoolean**, and also recognize only this limited set of string values as boolean values. Examples include **string is boolean**, **string is true**, **string is false**, and **fconfigure $chan -blocking**. Examples from Tk include configuration options of the **canvas**, **text**, and **scrollbar** that expect boolean values. The **Tcl\_ExprBoolean\(\)** routine interprets the result of an expression evaluation as a boolean. It recognizes all the values recognized by **Tcl\_GetBoolean\(\)**, but it also recognizes all numeric values as booleans as well. Any string which Tcl can interpret as any kind of number is a boolean according to **Tcl\_ExprBoolean\(\)** with the non-zero numbers seen as true, and others seen as false. Script-level commands such as **if** and **while** have adopted this view of booleans, so a script like **while \{[incr x -1]\} \{\}** works as expected. It also means the script **if 0x1 \{\}** is perfectly acceptable, even though **string is boolean 0x1** reports that **0x1** is not a boolean. The **Tcl\_GetBooleanFromObj\(\)** routine arrived in Tcl 8.0, and contrary to what its name might suggest, it was and is not an Obj-ified form of **Tcl\_GetBoolean**. Instead, **Tcl\_GetBooleanFromObj\(\)** adopted the **Tcl\_ExprBoolean** understanding of what was and was not a boolean value. Over time as more Tcl and Tk commands were Obj-ified, it was natural to replace **Tcl\_GetBoolean** calls with **Tcl\_GetBooleanFromObj** and in the process several commands have come to accept a broader class of boolean values than they once did. For example, % info patch 7.6p2 % clock format 0 -gmt 0x1 expected boolean value but got "0x1" % info patch 8.0.5 % clock format 0 -gmt 0x1 Thu Jan 01 00:00:00 GMT 1970 Another \(accidental?\) change in behavior in **Tcl\_LinkVar\(\)** sneaked in with the [[72]](72.md) changes between Tcl 8.3 and Tcl 8.4. A linked variable of type **TCL\_LINK\_BOOLEAN** now allows the Tcl variable to hold any numeric value, while in pre-8.4 releases of Tcl, only those values acceptable to **Tcl\_GetBoolean** were permitted. Tcl's built-in math functions include three that are devoted to "casting" operations, **int\(\)**, **double\(\)**, and **wide\(\)**. In each case, the result of the function is a string that passes the corresponding **string is** test. For example, string is integer [expr {int($x)}] will either return **1**, or raise an error; it will never return **0**. # Proposed Change Add a new built-in unary math function **bool\(\)** that accepts all values accepted by **Tcl\_GetBooleanFromObj\(\)** and returns one of the boolean values **0** or **1**, which are acceptable to **Tcl\_GetBoolean**. With that definition in place, string is boolean [expr {bool($x)}] will either return **1**, or raise an error; it will never return **0**. # Reference Implementation A "quick and dirty" implementation would be \(see [[232]](232.md)\): proc ::tcl::matchfunc::bool x {expr {!!$x}} A preferred implementation is at Tcl Patch 1165062. <http://sourceforge.net/support/tracker.php?aid=1165062> The preferred implementation has somewhat nicer error message reporting, and has greater potential for bytecode performance improvements. # Rationale First, this simply makes a nice parallel with the existing "casting" functions. It does away with the surprise expressed by some that a language making use of doubles, integers, and booleans provides **double\(\)** and **int\(\)**, but not **bool\(\)**. Second, because we have this bifurcated opinion about what values really count as boolean values, the proposed math function provides to the script level a way to safely accept booleans in the broader sense, even if using an interface that may be narrow. fconfigure $chan -blocking [expr {bool($value)}] This is, of course, equivalent to fconfigure $chan -blocking [expr {!!$value}] but should be easier on the code-reading eyes. # Copyright This document has been placed in the public domain. |
Name change from tip/183.tip to tip/183.md.
|
| < | < | | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 183: Add a Binary Flag to [open] Author: Andreas Leitgeb <[email protected]> Author: Don Porter <[email protected]> State: Final Type: Project Vote: Done Created: 24-Mar-2004 Post-History: Keywords: Tcl Tcl-Version: 8.5 ----- # Abstract To handle binary files, one currently has to open the file, and then in a second step **fconfigure** it with **-translation binary**. This TIP proposes to add a flag "b" to open's _access_-argument to set initial translation to binary \(rather than auto\). # Rationale ANSI-C _fopen\(\)_ supports an additional flag "b" in the _mode_ parameter especially for non-POSIX platforms, where it makes sure that no conversion takes place at reading or writing. The manual page for open mentions that **fconfigure** should be used as a substitute for the missing "b"-flag but I don't see anything wrong with a "b" flag as a possible shortcut for this **fconfigure**-call, so this TIP proposes that the _access_ argument to **open** should support **b** as an additional letter \(anywhere within the argument when used in the first form documented on the manual page\) which will cause the initial configuration of the channel to be suitable for reading and/or writing binary data. Thus, for an expectedly very little implementation effort, we can simplify: set fd [open $fname "w"]; fconfigure $fd -translation binary to: set fd [open $fname "wb"] which looks much more concise for such a common task. This extra flag would only affect the initial translation state. # Enhancement Tcl's **open** also tries to adopt the POSIX _open\(\)_ parameters \(i.e. the second form documented for the _access_ parameter on the manual page.\) POSIX's _open\(\)_ doesn't know about binary or non-binary files, but Tcl does, so a new keyword "BINARY" could be introduced to offer this feature also to those who prefer list-of-flags syntax. # Implementation A patch attached to Tcl Feature Request 577093 implements this proposal. The public Tcl C routine **Tcl\_FSOpenFileChannel** is amended to accept the **b** and **BINARY** substrings in its parsing of the _modeString_ argument. If this proposal is accepted, additional work will be performed to add the required test and documentation changes to the patch. # Compatibility Any remaining callers of the obsolete private interface **TclOpenFileChannelInsertProc** need to be aware that the _\(TclOpenFileChannelProc\_ \*\)_ function\(s\) it registers will now possibly be passed a _modeString_ argument that includes the newly supported **b** and **BINARY** substrings. Some updating will be required to handle this situation. Ideally, the updating will take the form of leaving behind use of this obsolete, unsupported, private interface, and migrating to the public support for virtual filesystems. Other than that, this proposal is a completely compatible extension of existing interfaces. # Discussion There have been comments that the C-like version of access is just legacy, hard to grok/remember and other general bad things about even the existing things. Those who don't like/use "r","w", "r\+", anyway, \(and who always use \{WRITE CREAT TRUNC\} instead of just "w"\) are not affected by any additional "b". There is no **need** to use it that way. fconfigure still remains. \(Partially I agree with them, the "r\+" and "w\+" are indeed lousy, and "a" is just a legacy design-bug -- seeks to end just once instead of before each write. Using that is like begging for race-conditions to bite. -- On the other hand "r" and "w", with or without "b" are unbeatably concise and still self-explaining.\) Some proposed adding -options for all kinds of things. Specifying the access-options as -read or -write ... My comment to this: If you like it verbose, use list-syntax for access-flags. This TIP is **not** about getting rid of legacy-C-syntax for flags. Some said, that if "b" \(BINARY\) is added, then sooner or later every fconfigure option would have to be added to "open", \(and some even proposed that\). Thats beside the point. Does anybody really doubt that "-translation binary" is by far the most common option used with fconfigure? And open does really ask for that but not for any other one \(at least not as loudly :-\). Another comment was about difficulties to implement "b", because lower-level functions \(Tcl\_FSOpenFileChannelProc was mentioned\) would have to be changed for that. That is not true, because the "b" could be recognized at top level \(Tcl\_OpenObjCmd\) and trigger the call to Tcl\_SetChannelOption after returning from the lower levels. \("b" is valid already, just currently ignored at all levels\). "open binaryfile r -translation binary" is not really any convenience. It's almost as verbose as calling fconfigure explicitly. Two positive comments appeared: First by Vince Darley: Having the Tcl C-Api for open accept the "b" makes it easier for foreign libraries \(that open binary files\) to be integrated as far as exposing them to Tcl's VFS, by \#define'ing fopen to the Tcl-C-Api function. Another, by DKF: The reasons of the current status quo are historical: the flags-argument for open was defined when Tcl was only \(officially\) available on Unix-platforms \(where "b" is ignored\) and didn't even support binary data \(nor any translations\). Both of these historical reasons are obsolete by now. To sum up: yes, "b" is a C-ism, but open is, too. Also it's not a feature that someone would be required to use. # Copyright This document has been placed in the public domain. |
Name change from tip/184.tip to tip/184.md.
|
| < | < | | | | | | | | > | | | | | | | | | | | | | < | > | | | | | | | | > | 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 | # TIP 184: Avoid Creating Unusable Variables Author: Miguel Sofer <[email protected]> State: Final Type: Project Vote: Done Created: 27-Mar-2004 Post-History: Keywords: Tcl, upvar, global Tcl-Version: 8.5 ----- # Abstract Both **upvar** and **global** can create unreachable variables: scalar variables whose name looks like an array element, e.g., a\(b\). This behaviour is documented in the **upvar** manpage. This TIP proposes that both **upvar** and **global** raise errors instead of creating such variables. # Rationale As detailed in [Bug #600812] <http://sf.net/tracker/?func=detail&aid=600812&group_id=10894&atid=110894> , both **upvar** and **global** can create unreachable variables: scalar variables whose names looks like an array element. One example is: upvar 0 x(1) y(1) which creates a _scalar_ variable named y\(1\) that is linked to the element 1 of the array x. However, there is no way for a tcl script to read or write such scalar variables, the parser will interpret that name as referring to an element of the array named y. Another example is: proc a {} { global x(1) ... } which will create a scalar local variable named 'x\(1\)', linked to the element 1 of theglobal array x. Again, this variable is unreachable. This TIP proposes **upvar** and **global** raise an error rather than creating such a variable, mimicking in this respect the behaviour of **variable**. Note that a TIP is required because the behaviour of **upvar** is documented in the manual page, so that it cannot really be described as a bug: > MyVar is always treated as the name of a variable, not an array element. Even if the name looks like an array element, such as a\(b\), a regular variable is created. # Reference Implementation There is a patch attached to the bug ticket <http://sf.net/tracker/?func=detail&aid=600812&group_id=10894&atid=110894> that implements this TIP. # Copyright This TIP is in the public domain. |
Name change from tip/185.tip to tip/185.md.
|
| < | < | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | < > | | | | | | | | | | | | | | | | | | | | | | | | < > | | | < > | | | | | | | | | | | | | | | | | | | | < | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 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 | # TIP 185: Null Handling Tcl-Version: 8.6 Author: John H. Harris <[email protected]> Created: 08-Apr-2004 Type: Project State: Rejected Vote: Done Post-History: Keywords: Tcl, absent value ----- # Abstract Tcl lacks the ability to handle _nulls_, data with missing or unknown values. In this TIP I suggest a means for representing and propagating nulls, and command modifications for manipulating them. # Rationale Tcl deals with strings, the universal medium for representing data. It lacks, however, the intrinsic ability to represent _missing_ data, or _nulls_. A null datum \(or just "null"\) is very different from an empty string. A database may represent Prince's last name as "" -- his name is know and it is an empty string, but if a respondent forgets to give his weight on a questionnaire, he is not weightless; his weight is not ""; it is unknown, or _null_. Nulls are common in real-world data, particularly data obtained from interviews or questionnaires. Because of this, most modern database engines and statistics tools recognize nulls. A large fraction of the applications we are writing are client programs to such databases, though the user is not always aware of it. The programmer can use whatever is provided with the database application program interface \(API\) he is using, but most Tcl APIs provide none, probably because Tcl itself lacks nulls. A Tcl programmer writing an interface to a database must improvise something to deal with nulls. If the data representation domain does not include an empty string, as for an integer or date, then an empty string may suffice, but arbitrary-string data is common, so something fancier is often needed. For example, here is an approach I used in a current project built on SQLite [[1]](1.md). I prepend each nonnull string with an apostrophe. Thus, nulls are universally represented by an empty string. I accomplish this using the _coalesce\(\)_ function provided by SQLite, e.g., if I want select id, name from persons I must ask for select id, coalesce(''||name,'') as name from persons I wrote a layer that automates this ugly mess. To keep it simple \(and because SQLite is untyped\) it prepends _all_ fields with an apostrophe, even ones that do not need it. I deal with the apostrophes later -- testing for nullness is easy, but the apostrophe gets in the way for most other I/O and processing. This is more than you wanted to know about my personal problems, but you can be sure this kind of thing is happening over and over with hundreds of programmers and applications. Now let us imagine how it might be simplified, assuming Tcl null support and a revamped SQLite API: set result [ db eval {select id, name from person} foreach -null <unknown> { id name } $result { puts "$id: $name" } I will explain more later, but basically, the database returns null information on _every_ query, so there is no fancy SQL code. The **-null** option tells **foreach** how to represent a null when it assigns _id_ and _name_. # Specification It would be nice if null handling could be added to, or with, a single command suite. If we could just extend, say, the **dict** command, these objects would be ideal media for database APIs. Unfortunately, it seems impossible to implement any change with out involving Tcl's string implementation, list syntax, and command interpreter. ## Representing Nulls Not all commands will understand nulls. We will speak of null-smart and null-dumb commands. All commands follow these rules: 1. Nulls represent a lack of information. 2. An empty string is not null. 3. Nulls can not be made "unnull", merely by being processed. This is equivalent to creating information out of thin air. Substituting a nonnull value for a null must programmed explicitly. 4. For null-smart commands, nulls propagate. A null combined with any nonnull is null. Appending a null to a string, or substituting a null into a string nulls the entire string. 5. Logical comparisons with nulls with respect to magnitude or identity evaluate to null \(i.e., _unknown_\). 6. Null-dumb commands must treat nulls as empty strings. ### Strings Objects An empty string is not a null. We have the further constraint that we must be able to handle any arbitrary binary string, including null \(in the sense of 0x00\) bytes. Clearly the implementation must be augmented; we must add a null flag. In implementation, null strings would probably have their string part set to an empty string, to accommodate null-dumb commands, as in rule 6 above. Thus, dumb commands can simply ignore the null flag. ### List Syntax It is easy to add a null flag to the string class. To be of any use, however, we need to pass a null string to commands, which means embedding nulls in lists. We can indicate this much in the same way the _\{expand\}\{\}_ syntax [[157]](157.md) works, by exploiting otherwise illegal list syntax. I propose using **\{null\}!** as null representation for lists. \(Perhaps new syntax could be a rider on the _\{expand\}\{\}_ rule. I fear that increasing the number of rules could scuttle this TIP.\) At present this syntax \(like \{expand\}\{\}\) produces an "extra characters after close-brace" error. Note that the string "\{null\}!" is _not_ interpreted as a null string, instead it is a nonnull string that is also a well-formed list with one null element. ### Interpreter Behavior If the command interpreter encounters the word "\{null\}!" in a list, this element is replaced by a null string in the array of strings passed to the command. When the Tcl command interpreter encounters a word that contains a variable substitution, if the variable contains a null, the interpreter will behave as if the entire word were replaced with "\{null\}!", and pass a null string to the command in its place. Command substitutions behave the same way when a command returns a null. ## Manipulating Nulls We need not be decided how commands should respond to nulls all at once. Indeed, it would be better to let this evolve as we gain experience with this new dimension of data. At first we will need at least some basic support to create, copy and test nulls. ### The String Command The simplest approach is simply to test for nullness. The obvious candidate for this test would be an addition to the _string is_ command suite: if { [ string is null $s ] } { error {Missing data for s.} } The string command could also be used to generate nulls: set null [ string null ] ### The Set Command We can use _set_ to create a variable that contains a null string: % set s {null}! Now _s_ exists and has its null flag set. This is such a natural syntax that it probably make _string null_ unnecessary. We can retrieve a null value with _set_ -- suppose _puts_ is dumb and sees the null as an empty string: % puts "s equals [ set s ]" **Set** returns a null. In this case, the null is in a command substitution, and it nulls the entire string being passed to **puts**, which, being null-dumb, outputs an empty string and newline. This may be unsatisfactory. We would rather substitute a nonnull, perhaps an empty string, or "<NULL>". When and what to substitute is an ad hoc programming choice, so should be an option. Here is the _set_ command with an option that tells how to represent a null: % set s {null}! % set -null <NULL> s <NULL> % set -null huh? s huh? The default value for this option is a null, so **[set s]** can be used as a direct substitution for **$s**, as you would expect. While we must allow for the worst case of representing a null amidst the set of arbitrary binary strings, in practical data this seldom occurs. When it does, we must resort to an explicit test and conditional execution, but more often there is some gap in the domain of valid data that can be used to represent a null. We have already seen the example of using and empty string for a null integer or date. For other data types there are better choices. The programmer knows these gaps and can choose a string that fits in the gap and is also easily understood by humans or other software. The **-null** option should have the same meaning when applied to any null-smart command: if the return value is a null, change it to the option value. The set command can use a similar option to assign a null. This time the option **-nullify** tells what value, by exact match, should be replaced by a null. % set s NULL NULL % set -nullify NULL t $s % puts '[ set -null Void t ]' 'Void' Notice that string _s_ above is _not_ a null, it is the string "NULL". The second command translates it to a true null, and the third translates it to "Void". The **-nullify** option provides a way of assigning a null to a variable that is independent of list syntax: % set -nullify {} s {} The **-nullify** option should have the same meaning when applied to any null-smart command: if an argument value is an exact match to the options value, change it to a null. ### List Commands Most smart commands can just test the null flag of their arguments and take appropriate action. A few commands, such as **lindex**, **lset**, **join**, and **split** must understand list null syntax. Consider the string: % set s {a {b0 {null}! b2} c} This string represents a list whose second element is a list containing a null. We expect this behavior: % lindex -null ~ $s 1 1 ~ % lset -nullify {} s 1 2 {} a {b0 {null}! {null}!} c % lindex -null NUL $s 1 2 NUL **Join** creates a string from a list and must understand **-null**. Notice that the second command below returns null, by rule 4. % join -null void {a {null}!} a void % join {a {null}!} **Split** creates a list from a string and must understand **-nullify**: % split {a {null}!} a {{null}!} % split -nullify NULL {a NULL} a {null}! ### Expr and Control-flow Commands Nulls can be tested using **string is null**, but testing occurs so often in practice that we need to have **expr** and the control commands behave properly, allowing three-valued logic -- true, false, and null. \(In this context, a logic value of null is often called "unknown".\) **Expr** should recognise the **-null** option. These examples illustrate typical three-valued logic tautologies: % set u {null}! % expr -null unk { $u } unk % expr -null unk { $u && 1 } 1 % expr -null unk { $u && 0 } unk % expr -null unk { $u || 0 } 0 % expr -null unk { $u == $u } unk % expr -null unk { $u != 1 } unk % expr -null unk { $u eq {} } unk % expr -null unk { $u > 0 } unk Notice that, logic expressions containing nulls may may have nonnull results. This my seem like a violation of rule 5, but actually is is just a special kind of lazy logic. **Expr** can simply ignore the null term because it is tautologously irrelevant. The control commands **if**, **while**, and **for** all throw errors if the expression evaluates to null. We can also use nulls to represent undefined mathematical results, or _NaN_s \(not a number\), in the terminology of IEEE 754 floating point arithmetic [[2]](2.md). This allows Tcl to give the programmer access to hardware features that are currently hidden. To do this we need a **-nocomplain** option: % expr -nocomplain -null nan { log(-1) } nan We can use the **-null** option to assign a usable value if _a_ goes to zero: % set INF 1e16 % set x [ expr -nocomplain -null $INF { 5 / $a } ] Nulls can propagate sensibly through a computation and give a useful result when, without them, the same expression would have throw an exception. Again, suppose _a_ goes to zero: % expr -nocomplain -null unk { $x / $a > 0.54 || $c < 0.042 } 1 ### Other Basic Commands We need not make all commands null-smart immediately. Old commands can treat nulls as empty strings and function as before. They may be less useful than they could be, but nothing need break, because old code contains nothing that would introduce nulls in the first place. It is up to the programmer who decides to use Tcl's null facility to be aware of which commands respond intelligently to nulls. Perhaps a greater danger is that, once nulls are introduced, evolving commands may break applications that use nulls. Because of this, it would be wise to choose the initial set of null-smart commands with care. I propose modifying the following commands, if necessary, to respond to nulls appropriately: **lset**, **foreach**, **format**, the list commands, **return**, **set**, **subst**, **string**, **switch**. Except as noted below, this means recognizing the **-null** option. Now let us discuss the modifications needed for these commands. String command suite: Except for **string is** commands, all **string** subcommands should return null if any argument is null, simply because the commands are meaningless when applied to a null string. > Note that a null string is not unequal to any given string. Batman may or may not be Bruce Wayne -- his identity is unknown. Similarly, two null strings are neither equal nor unequal to each other. Batman may or may not be the same guy as the Lone Ranger. String is: Except for **string is null**, all **string is** subcommands return 0 with a null argument. Switch: The switch command should recognize the **-null** option. Having a switch leg that matches null is easy to imagine: switch $s { a { do this } b { do that } {null}! { punt } } > but by rule 5 it would never execute -- nothing matches a null. Instead, use **-null**: switch -null NULL $s { a { do this } b { do that } NULL { punt } } > If you must match any other nonnull string separately from nulls, use **-glob** and catch the null with _default_: switch -glob -null NULL -- $s { a { do this } b { do that } * { any other nonnull } default { punt } } Foreach: The **Foreach** command recognizes both **-null** and **-nullify**. Format: The **format** command should understand the **-null** option. The list commands: In general, all the list commands treat nulls as distinct elements. Nulls never disappear from a list. **llength** includes them in the count. Commands that convert lists to or from strings \(**lappend**, **lindex**, **linsert**, **list**, **lset**, **split**, **join**\) should understand the **-null** option. Those that stay in the list domain \(**concat**, **lrange**\) should not. lsort: If a list contains a null it cannot be sorted -- **lsort** returns a null string. With the **-null** option, it can be sorted after substituting the **-null** option value. # Issues and Extensions In this section we discuss design issues that are either debatable or not entirely resolved. * Null attributes. It is common practice in statistics to have several distinct kinds of null. In the SAS language, a null datum can be represented by a period, '.', or a period followed by a letter, '.a'. Different codes represent different reasons for the null, e.g., .a = "no response", .b = "doubly-entry error", .c = "out of range". > Another use of a null attribute would be to have a value carry its string representation. > I think both these ideas are of dubious value and violate rule 1, but if, in the future, we want to add this functionality, it could be added with the syntax \{null\}\{\}, where the second set of braces contain the attribute information. * Choice of symbol. > \{null\}! or NULL, void, nan, unk, unknown, \{\}!, * SQL inconsistencies. The various implementations of SQL are inconsistent in their treatment of nulls. This is well documented on both the SQLite [[1]](1.md) and MySQL [[3]](3.md) web sites. I prefer a conservative, consistent mathematical interpretation. The **-null** and **-nullify** options go a long way toward simulating the inconsistencies of other systems, if necessary. # Discussion # References [[1]](1.md): SQLite [[2]](2.md): IEEE Floating point [[3]](3.md): MySQL # Copyright This document has been placed in the public domain. |
Name change from tip/186.tip to tip/186.md.
|
| < | < | | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 186: Expose the Type and Modified-State of Widget Options Author: Peter MacDonald <[email protected]> Author: Peter MacDonald <[email protected]> State: Draft Type: Project Vote: Pending Created: 16-Apr-2004 Post-History: Keywords: Tk Tcl-Version: 8.7 ----- # Abstract This TIP adds a 6th \(and 7th element\) to each option in the output of [_path_ **configure**] for Tk widgets, indicating the type and modified status of each option respectively. # Rationale The configure subcommand of Tk widgets provides a powerful method for introspection of widget state information. Unfortunately, two important pieces of information are currently unavailable. Namely, the type Tk is expecting for an option and the whether a user has explicitly assigned a value. The type field is valuable in automating interfaces for editing the contents of widgets. The modified field is useful in changing styles \(such as in **tk\_setPalette**\) where we update all widgets that are currently using default values. # Specification The configure subcommand for Tk widgets, when invoked with no arguments, currently dumps out all options as a list with 5 elements per-option: optName, dbName, dbClass, defValue, optValue. This TIP proposes adding up to 2 additional values: **optType** and **optModified**. * A 6th element, **optType**, is a string representation of the type field of **Tk\_ConfigSpec** and **Tk\_OptionSpec**. * For widgets using the new **Tk\_OptionSpec**, a 7th appended element indicates whether an option has been set by the user. # Notes Perhaps **optModified** should be specified as an enumeration. For example: * 1 = **USER\_MODIFIED** * 2 = **OPTION\_DATABASE** * 3 = **SYSTEM\_DEFAULT** * 4 = **TABLE\_DEFAULT** In addition, as much of the Tk core is still using **Tk\_ConfigSpec**, would some form of compatibility interface make sense whereby a **Tk\_ConfigSpec** could be used to dynamically produce a **Tk\_OptionSpec**? \(This last is out of the scope of this TIP.\) Probably also need a way to change options such that the **USER\_MODIFIED** flag does not get set. \(eg. **tk\_setPalette**\) # Changes Threre are a couple of small changes to _tkConfig.c_ and _tkOldConfig.c_, plus a \#define of **TK\_OPTION\_VALUE\_SET** in _tk.h_ # Overhead/Impact Scripts currently exploiting introspection and depending upon a list length of 5 may break. # Reference Implementation There is a simple implementation of the above available as a patch against Tk 8.4.2<http://pdqi.com/configure.diff.gz> . It does not implement a enumerated flag for **optModified**, and the type string lookup is rather crude. # Copyright This document has been placed in the public domain. |
Name change from tip/187.tip to tip/187.md.
|
| < | < | | | | | | | | | | > | | | | | | | | | | | | | | | | | | | < > | < > | | | | | | | | | < < > > | < > | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 187: Procedures as Values Author: Salvatore Sanfilippo <[email protected]> Author: Miguel Sofer <[email protected]> Author: Paul Nash <[email protected]> State: Rejected Type: Project Vote: Done Created: 20-Apr-2004 Post-History: Keywords: Tcl,lambda,anonymous,command,function Tcl-Version: 8.6 ----- # Abstract This TIP describes a change in the semantics of Tcl to allow procedures to be first class values, being represented as strings, and in particular as three element lists. # Rationale The Tcl programming language is an homoiconic-form language. Program and data are both presented as strings. A Tcl procedure's arguments list and body are not an exception to this rule, but the procedure itself is handled as a name bound to a particular couple of arguments list and body. This name lives in a separated namespace and does not collide with variables names. The first argument of every Tcl command should be the name of a built-in command, or a procedure \(actually a procedure is a user defined command\). In the latter case, the Tcl interpreter performs a lookup in a virtual table \(that is indirectly accessible using **proc** and **info** commands\), in order to check if there is a procedure with the specified name, and to call the procedure using the associated arguments list and body. If a procedure with the specified name is not present \(nor a built-in command\), the interpreter calls a special procedure named unknown to handle the exception, or raises an error if the unknown procedure does not exists. This TIP proposes to modify the Tcl semantic in order to check if the command name is a valid, three-elements Tcl list with the first element of the list being the string **lambda**, before to lookup any built-in command or procedure. In such a case Tcl will call the procedure that is represented by the arguments list and body that are the second and third elements of the list. Procedures represented as three-elements lists are called _anonymous procedures_ in this TIP, and are first class values as any other Tcl list. The storage of an anonymous procedure is handled like any other Tcl object. Memory management is one of the main problems of procedures created "on the fly" in Tcl, so that to create anonymous procedures in Tcl in order to emulate the lambda operator, was and is a problem. With this TIP, anonymous procedures can be created just using the list command. The following is an example: set p [list lambda x {string length $x}] $p foo The above script evaluates to 3. Fast, reliable anonymous procedures may allow Tcl to better support a functional approach that is very interesting to use in a language where the list is the main data structure. ## Examples The following Tcl scripts \(based on the classic list combinators from functional programming languages\) should look very natural to most experienced Tcl programmers: ### Example 1: Use of Anonymous Commands with a [map] Command proc map {list proc} { set res {} foreach e $list { lappend res [$proc $e] } return $res } set a [list one two three four five] set b [map $a [list lambda x {string length $x}]] This evaluates to [list 3 3 5 4 4] ### Example 2: Use of Anonymous Commands with a [filter] Command proc filter {list proc} { set res {} foreach e $list { if {![$proc $e]} { lappend res $e } } return $res } set a [list 1 10 100 4 5] set b [filter $a [list lambda x {expr $x<10}]] This evaluates to [list 10 100] Note: In practice, defining an alias, **lambda**, for **list lambda** leads to more natural-looking code. <PN> (bin) 20 % list lambda x {string length $x} lambda x {string length $x} (bin) 21 % lambda x {string length $x} lambda x {string length $x} (bin) 22 % No alias is required </PN> The author of this TIP thinks that many Tcl programmers will enjoy the ability to use this programming style. The Tcl folklore actually implemented different versions of **lambda** in the past, but no one is suitable for prime time. Still, the ability to manipulate lists in a simpler way can make Tcl more enjoyable. The new semantic introduced by this TIP is not only needed to use operators like _map_ and _filter_, but generally makes Tcl able to address high-order programming in a clean way: procedures that returns procedures, Currying, and functional composition are all possible using the TIP's first class procedures in a straightforward way. There are probably other interesting applications in the field of the Object Oriented Programming. # Proposed Change The proposed change is to check if the first argument of a command is an anonymous procedure before to perform any other lookup. This test should be fast using the object's string representation because a Tcl list having as first argument the string "lambda" must start in a proper way that is easy to detect. The procedure can be byte-compiled when it's called the first time, the byte-compiled version can be referenced from the internal representation of the _Tcl\_Obj_ representing the procedure. The original string representation of the anonymous procedure can be cached inside the _Tcl\_Obj_ in order to be able to recreate it when needed as for _Tcl\_Obj_ semantic. Actually the implementation may create a conventional Tcl procedure associated and referenced by the anonymous procedure's object, that can be released when the internal representation of the anonymous procedure's _Tcl\_Obj_ is freed. The real Tcl procedure may live in the **::lambda** namespace in order to be self-introspective. # Reference Implementation A reference implementation is being developed in Patch \#940207 \(superseeding the previous \#939190\) <https://sourceforge.net/tracker/index.php?func=detail&aid=940207&group_id=10894&atid=310894> It follows this tip fairly closely in its effects, but diverges in the implementation strategy. It implements autocleaning procs, and defines lambda expressions as autocleaning procs in \(for instance\) the ::tcl::lambda namespace. The example above can be defined equivalently as set p [lambda x {string length $x}] set p [list ::tcl::lambda:: x {string length $x}] set p {::tcl::lambda:: x {string length $x}} although the last version will prevent autocleanup \(due to the name being stored in a shared literal\). # Copyright This document has been placed in the public domain. |
Name change from tip/188.tip to tip/188.md.
|
| < | < | | | | | | | | | > | | | | | | | | | | | | | | | | | | > | 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 | # TIP 188: Add 'string is wideinteger' to the 'string is' Subcommand Author: Kevin Kenny <[email protected]> State: Final Type: Project Vote: Done Created: 23-Apr-2004 Post-History: Discussions-To: news:comp.lang.tcl Keywords: Tcl Tcl-Version: 8.5 ----- # Abstract The **string** command supports tests for a number of Tcl's basic types, for example, integers, doubles, and booleans. This TIP proposes adding wide integers. # Rationale The **string** command includes tests for the common Tcl types: **string is boolean**, **string is double** and **string is integer**. Unaccountably, **string is wideinteger** is missing from the list, making it difficult for an input validation procedure to determine whether, in fact, a string contains a valid wide integer. # Specification This document proposes augmenting the **string is** command with a **string is wideinteger** that functions the same as **string is integer** in every respect except for the fact that it accepts any string containing a substring that is valid as a wide integer \(that is, acceptable to _Tcl\_GetWideIntFromObj_\) possibly surrounded by whitespace. # Reference Implementation Patches that implement **string is wideinteger**, provide test cases for it, and update _doc/string.n_ to include it are available at SourceForge as Tcl Patch \#940915<http://sf.net/tracker/?func=detail&atid=310894&aid=940915&group_id=10894> . # Copyright Copyright 2004, by Kevin B. Kenny. Redistribution permitted under the terms of the Open Publication License <http://www.opencontent.org/openpub/> . |
Name change from tip/189.tip to tip/189.md.
|
| < | < | | | | | | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | 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 | # TIP 189: Tcl Modules Author: Andreas Kupries <[email protected]> Author: Jean-Claude Wippler <[email protected]> Author: Jeff Hobbs <[email protected]> Author: Don Porter <[email protected]> Author: Larry W. Virden <[email protected]> Author: Daniel A. Steffen <[email protected]> Author: Don Porter <[email protected]> State: Final Type: Project Vote: Done Created: 24-Mar-2004 Post-History: Tcl-Version: 8.5 ----- # Abstract This document describes a new mechanism for the handling of packages by the Tcl Core which differs from the existing system in important details and makes different trade-offs with regard to flexibility of package declarations and to access to the filesystem. This mechanism is called "Tcl Modules". # Background and Motivation The current mechanism for locating and loading packages employed by the Tcl core is very flexible, but suffers from a number of drawbacks as well. These are at least partially the result of the flexibility, and thus not easily solved without giving up something. One problem with the current mechanism is that it extensively searches the filesystem for packages, and that it has to actually read a file \(_pkgIndex.tcl_\) to get the full information for a prospective package. All of these operations take time. The fact that "index scripts" are able to extend the list of paths searched tends to heighten this cost as it forces rescans of the filesystem. Installations where directories in the _auto\_path_ are large or mounted from remote hosts are hit especially hard by this \(network delays\). All of this together causes a slow startup of tclsh and Tcl-based applications. "**Tcl Modules**" on the other hand is designed with less flexibility in mind and to allow implementations to glean as much information as possible without having to perform lots of accesses to the filesystem. Additional benefits of the proposed design are a simplified deployment of packages, akin to the way starkits made application deployment simple, and from that an easier implementation and management of repositories. It does not come without penalties however. * The simplified design has no "index scripts". While this does away with extending the list of paths for searching, it also does away with the ability of packages to check preconditions, like the version of the currently executing Tcl interpreter. Dependencies of packages \(in module form\) on particular versions of Tcl have to be managed differently and outside of them. * "Tcl Modules" is defined to be an extension of the existing package mechanism and does _not_ replace it. This means that any failure to find a package as a module _has to_ cause a fall back to the regular package mechanism. It also sets a limit on how much of our goals we can reach: searching for packages which are not installed will stay relatively slow, and dominated by the filesystem scan of the regular search. This implies that "Tcl Modules" will be best suited in installations where the number of regular packages is low, and contained in a small part of the overall filesystem. > On the gripping hand, the only regular packages required will be packages supporting the virtual filesystems employed by modules \(more on that later\), so a transformation of a installation based on a set of regular packages to the form above is quite feasible. # Specification ## Introduction Modules are regular Tcl Packages, in a different guise. To ease explanations, first a summary of the existing mechanism: * Packages are identified through "_pkgIndex.tcl_" files and the "index script" they contain. These files are read and define the "provide script", which tells Tcl how to actually load the package. In other words, the provide script tells whether to use the "**source**" or "**load**" command, which file to specify as an argument to that command, etc. However as "_pkgIndex.tcl_" contains a regular tcl script, it can do more than that and actually influence the environment, i.e., the package search itself, in several ways: > \* It may choose to not register the package if conditions for the package are not met, like being run by a too old version of Tcl. > \* It may extend the list of paths used to search for packages. This implies that a package is able to modify the behaviour of the package search \(usually extending the search\) even before it is loaded, and even if it will not be loaded at all. The above is very flexible, but comes at a price. The filesystem is not only searched, but files have to be read as well to build up the in-memory index of packages. And this is iterated if index files change/extend the list of paths to search. |
︙ | ︙ | |||
117 118 119 120 121 122 123 | * What constitutes a Tcl Module ? * How are they found ? * How are they indexed, i.e. entered into the package database ? | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 | * What constitutes a Tcl Module ? * How are they found ? * How are they indexed, i.e. entered into the package database ? ## Module Definition A Tcl Module is a Tcl Package contained in a _single_ file, and no other files required by it. This file has to be **source**able. In other words, a Tcl Module is always imported via: source module_file The "load" command is not directly used. This restriction is not an actual limitation, as we may believe. Ever since 8.4 the Tcl **source** command reads only until the first ^Z character. This allows us to combine an arbitrary Tcl script with arbitrary binary data into one file, where the script processes the attached data in any it chooses to fully import and activate the package. Please read [[190]](190.md) "Implementation Choices for Tcl Modules" for more explanations of the various choices which are possible. The name of a module file has to match the regular expression ([[:alpha:]_][:[:alnum:]_]*)-([[:digit:]].*)\.tm The first capturing parentheses provides the name of the package, the second clause its version. In addition to matching the pattern, the extracted version number must not raise an error when used in the command package vcompare $version 0 This additional check has several benefits. The regular expression pattern is a bit simpler, and the full version check is based on the official definition of version numbers used by the Tcl core itself. ## Finding Modules Remember the check for a valid module in last section, and notice that any filename matching this name pattern is going to be treated by the TM system as if it's a Tcl module, whether it really is or not. This means it's a bad idea for any non-Tcl module files that might match that pattern to end up in a directory where TM will be scanning. This suggests that the directory tree for storing Tcl modules ought to be something separate from other parts of the filesystem. This further implies that a new search path over just these separate storage areas would be better than Yet Another Use of _$::auto\_path_. Therefore: Modules are searched for in all directories listed in the result of the command "**::tcl::tm::path list**" \(See also section 'API to "Tcl Modules"'\). This is called the "Module path". Neither "_auto\_path_" nor "_tcl\_pkgPath_" are used. All directories on the module path have to obey one restriction: * For any two directories, neither is an ancestor directory of the other. This is required to avoid ambiguities in package naming. If for example the two directories foo/ foo/cool were on the path a package named 'cool::ice' could be found via the names 'cool::ice' or 'ice', the latter potentially obscuring a package named 'ice', unqualified. Before the search is started, the name of the requested package is translated into a partial path, using the following algorithm: * All occurrences of '::' in the package name are replaced by the appropriate directory separator character for the platform we are on. On Unix, for example, this is '/'. Example: * The requested package is _encoding::base64_. The generated partial path is encoding/base64 After this translation the package is looked for in all module paths, by combining them one-by-one, first to last with the partial path to form a complete search pattern. The exact pattern and mechanism is left unspecified, giving the implementation freedom of choice as to what glob searches to perform, how much of them, and when. Independent of that, the implemented algorithm has to reject all files where the filename does not match the regular expression given in the previous section. For the remaining files "provide scripts" are generated and added to the **package ifneeded** database. The algorithm has to fall back to the previous unknown handler when none of the found module files satisfy the request. If the request was satisfied no fall-back is required. ## Provide and Index Scripts Packages in module form have no control over the "index" and "provide script"s entered into the package database for them. For a module file _MF_ the "index script" is package ifneeded PNAME PVERSION [list source MF] and the "provide script" embedded in the above is source MF Both package name **PNAME** and package version **PVERSION** are extracted from the filename **MF** according to the definition below: MF = /module_path/PNAME'-PVERSION.tm Where **PNAME' **is the partial path of the module as defined in section 'Finding Modules' before, and translated into **PNAME** by changing all directory separators to '::', and **module\_path** is the path \(from the list of paths to search\) that we found the module file under. _Note_ that we are here creating a connection between package names and paths. Tcl is case-sensitive when it comes to comparing package names, but there are filesystems which are not, like NTFS. Luckily these filesystems do store the case of the name, despite not using the information when comparing. Given the above we allow the names for packages in Tcl modules to have mixed-case, but also require that there are no collisions when comparing names in a case-insensitive manner. In other words, if a package 'Foo' is deployed in the form of a Tcl Module, packages like 'foo', 'fOo', etc. are not allowed anymore. Regular packages have no problem with the names of their files, as their entry point has a standard name \("_pkgIndex.tcl_"\) and its contents can be adjusted according to the filesystem they are stored in. ## API to "Tcl Modules" "Tcl Modules" is implemented in Tcl, as a new handler command for **package unknown**. This command calls the previously installed handler when its own search fails, thereby ensuring proper fall-back to the regular package search. All code and data structures implementing "Tcl Modules" reside in the namespace "_::tcl::tm_". A namespace variable holds the list of paths to search for modules, but is not officially exported. All access to this variable is done through the following public commands: * **::tcl::tm::path add** _PATH_ > The path is added at the head to the list of module paths. > The command enforces the restriction that no path may be an ancestor directory of any other path on the list. If the new path violates this restriction an error will be raised. > If the path is already present as is, no error will be raised and no action will be taken. > Paths are searched in the order of their appearance in the list. As they are added to the front of the list they are searched in reverse order of addition. In other words, the paths added last are looked at first. * **::tcl::tm::path remove** _PATH_ > Removes the path from the list of module paths. The command is silently ignored if the path is not on the list. * **::tcl::tm::path list** > Returns a list containing all registered module paths, in the order that they are searched for modules. * **::tcl::tm::roots** _PATH\_LIST_ > Similar to _path add_, and layered on top of it. This command takes a list of paths, extends each with _tclX/site-tcl_, and _tclX/X.y_, for major version X of the tcl interpreter and minor version y less than or equal to the minor version of the interpreter, and adds the resulting set of paths to the list of paths to search. > This command is used internally by the system to set up the system-specific default paths. See section _Defaults_ for their definition, and that their structure matches what this command does. > The command has been exposed to allow a buildsystem to define additional root paths beyond those defined by this document. We do _not_ provide APIs for rescanning directories, clearing internal state and such. The official interface to this functionality is "package forget" and special interfaces are neither required nor desirable. # Discussion ## Restriction to "source" This has already been discussed in the specification above. For more discussion I again refer to [[190]](190.md) "Implementation Choices for Tcl Modules" which explains the various implementation choices in much more detail. ## Preconditions It has already been mentioned in section 'Background and Motivation' that preconditions in "index scripts" are lost, one of the penalties of the simplified scheme specified here. Their existence was most important to installations with multiple versions of Tcl coexisting with each other as they could share the directory hierarchy containing packages between the various Tcl cores. This is not possible anymore, at least not in a simple manner. For the majority of installations however, i.e. those without only one version of Tcl installed, or controlled environments like the inside of starkits and starpacks, this loss is irrelevant and of no consequence. For more discussion please see [[191]](191.md) "Managing Tcl Package and Modules in a Multi-Version Environment" which explains the various choices a sysadmin has in much more detail. ## Package Metadata An area possibly made harder by Tcl Modules is the storage and query of package metadata. [[59]](59.md) was one way of handling such information, by storing them in the binary library of packages which have such. Another approach was to store them in the package index script, using a hypothetical **package about** command. The latter approach has the definite advantage that it was possible to query the database of metadata for a particular package without having to actually load said package, as a load may fail if the Tcl shell used to query the database does not fulfil the preconditions for that package. Both approaches listed above assume that it makes sense to query the database of metadata for all installed packages from a plain Tcl shell. In other words, to use the standard Tcl shell also as the tool to directly manage an installation. It is possible to extend the proposal made in this document to handle metadata as well. We already reserved the namespace **::tcl::tm** for use by us, so it is no problem to extend the public API with commands to locate all installed packages, their metadata, and to perform queries based on this. This will require an additional specification as to how metadata is stored in/by Tcl Modules, and it will have to be understood that these extended management operations can take considerably more time than a **package require**, as they will have to scan all defined search paths and all their sub directories for Tcl Modules, and have to extract the metadata itself as well. ## Deployment The fact that a Tcl Module consists only of a single file makes its deployment quite easy. We only have to ensure correct placement in one of the searched directories when installing it locally, but nothing more. Regarding the usage of Tcl Modules in a wrapped application, please see [[190]](190.md) "Implementation Choices for Tcl Modules". This is highly dependent on the implementation chosen for a specific Tcl Module and thus not discussed here, but in the referred document. ## Package Repositories At a very basic level, the physical storage, any directory tree containing properly placed files for a number of modules can serve as a package repository for the modules in it. In other words, from that point of view an installation is virtually indistinguishable from a repository, and their creation and maintenance is very easy Note however that the higher levels of a repository, like indexing package metadata in general, or dependence tracking in particular, licensing, documentation, etc. are not addressed here and by this. This requires standards for package metadata, format and content, topics with which this document will not deal. ## Defaults The default list of paths on the module path is computed by a tclsh as follows, where _X_ is the major version of the Tcl interpreter and _y_ is less than or equal to the minor version of the Tcl interpreter. * System specific paths > \* **file normalize** [**info library**]/../tcl_X_/_X_._y_ > > In other words, the interpreter will look into a directory specified by its major version and whose minor versions are less than or equal to the minor version of the interpreter. > > Example: For Tcl 8.4 the paths searched are > > \* [**info library**]/../tcl8/8.4 > > \* [**info library**]/../tcl8/8.3 > > \* [**info library**]/../tcl8/8.2 > > \* [**info library**]/../tcl8/8.1 > > \* [**info library**]/../tcl8/8.0 > > This definition assumes that a package defined for Tcl _X.y_ can also be used by all interpreters which have the same major number _X_ and a minor number greater than _y_. > \* **file normalize** _EXEC_/tcl_X_/_X_._y_ > > Where _EXEC_ is [**file normalize** [**info nameofexecutable**]/../lib] or [**file normalize** [**::tcl::pkgconfig get** libdir,runtime]] > > This sets of paths is handled equivalently to the set coming before, except that it is anchored in _EXEC\_PREFIX_. For a build with _PREFIX_ = _EXEC\_PREFIX_ the two sets are identical. * Site specific paths. > \* **file normalize** [**info library**]/../tcl_X_/site-tcl * User specific paths. > \* **$::env**\(TCL_X_._y_\_TM\_PATH\) > > A list of paths, separated by either **:** \(Unix\) or **;** \(Windows\). This is user and site specific as this environment variable can be set not only by the user's profile, but by system configuration scripts as well. > > These paths are seen and therefore shared by all Tcl shells in the **$::env**\(PATH\) of the user. > > Note that _X_ and _y_ follow the general rules set out above. In other words, Tcl 8.4, for example, will look at these 5 environment variables > > \* **$::env**\(TCL8.4\_TM\_PATH\) > > \* **$::env**\(TCL8.3\_TM\_PATH\) > > \* **$::env**\(TCL8.2\_TM\_PATH\) > > \* **$::env**\(TCL8.1\_TM\_PATH\) > > \* **$::env**\(TCL8.0\_TM\_PATH\) _All_ the default paths are added to the module path, even those paths which do not exist. Non-existent paths are filtered out during actual searches. This enables a user to create one of the paths searched when needed and all running applications will automatically pick up any modules placed in them. The paths are added in the order as they are listed above, and for lists of paths defined by an environment variable in the order they are found in the variable. ## Installation The installation of a Tcl module for a particular interpreter is basically done like this: #! /path/to/chosen/tclsh # First argument is the name of the module. # Second argument is the base filename set mpaths [::tcl::tm::path list] ... remove all paths the user has no write permissions for. ... throw an error if there are no paths left. ... provide the user with some UI if more than one path is left ... so that she can select the path to use. set selmpath [ui_select $mpaths] file copy [lindex $argv 1] \ [file join $selmpath \ [file dirname [string map {:: /} \ [lindex $argv 0]]]] # Glossary The following terms and definitions are used throughout the document * _index script_ > A script used to index a package, or not. Usually contained in a file named "_pkgIndex.tcl_". Can check preconditions for a package and contains package specific code for setting up the package specific _provide script_. * _provide script_ > This is a package specific script and tells Tcl exactly how to import it. In the existing package system it is generated and registered by the _index script_. Tcl Modules on the other hand generates it based on information gleaned from filenames. # Reference Implementation A reference implementation is available in Patch 942881 <http://sf.net/tracker/?func=detail&aid=942881&group_id=10894&atid=310894> # Questions # Comments [ Add comments on the document here ] A feature asked for during discussion is to allow a directory as a Tcl Module. I am opposed to this, because behind Tcl Modules is the same idea/vision as for starkit and starpacks, namely that of deploying something in the simplest possible manner, without any overhead. Sometimes I call Tcl Modules package kits, short pakits \(and then twist that then spoken into 'packet' :\). <http://groups.google.ca/groups?hl=en&lr=&ie=UTF-8&frame=right&th=78764d499cc4e4a&seekm=c6tshf030c6%40news4.newsguy.com#link19> # Copyright This document has been placed in the public domain. |
Name change from tip/19.tip to tip/19.md.
|
| < | < | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | < < > > | < > | | | | | | | | | > | 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 | # TIP 19: Add a Text Changed Flag to Tk's Text Widget Author: Neil McKay <[email protected]> State: Final Type: Project Vote: Done Created: 03-Jan-2001 Tcl-Version: 8.4a2 Obsoleted-By: 26 Post-History: ----- # Abstract This TIP adds a _text changed_ flag to the Tk text widget. The flag would initially be reset, but would be set whenever the contents of the text widget changes. # Rationale When creating a text editor, it is often useful to know when the contents of the edit buffer have changed, e.g. in order to ask the user whether or not to save changes on exit. It is possible to create key bindings in Tk's text widget that will set a flag whenever the user changes the widget's contents; however, this is awkward, and it still requires that the programmer set the flag whenever text is changed programmatically. A better solution is to include a _text changed_ flag in the code for the text widget itself; this can be accomplished with a relatively small amount of code. # Flag Behavior The _text changed_ flag should behave as follows: * It should be reset when the text widget is created * It should be set whenever characters are inserted into or deleted from the widget * It must be resettable programmatically via a Tcl command # Reference Implementation At the Tcl level, one possible implementation is to add a _changed_ widget command to the text widget. One possible syntax for this command is: .txt changed ?boolean? where .txt is a text widget. With no _boolean_ argument, the command returns the state of the text-changed flag; with an argument, it sets the state of the text-changed flag to the value of the argument. # Example A typical sequence of commands in a text editor would be 1. Create a text widget 2. Read a file and put its contents into the text widget 3. Mark the text as unchanged 4. Edit the text 5. Write the text out, if it has changed. This could be accomplished by the following Tcl code fragment: grid [button .b -text Quit -command EndEdit] grid [text .t] proc EndEdit {} { if {[.t changed]} { set result [tk_messageBox -type yesno -message "Save changes?"] if {[string compare $result "yes"] == 0} { set fh [open $fileName "w"] puts -nonewline $fh [.t get 1.0 end-1c] close $fh } } exit } set fh [open $fileName "r"] .t insert end [read $fh] close $fh .t changed false # Copyright This document is in the public domain. # Patch The _changed_ text widget command, as described above, may be added to Tk8.4a2 by applying the patch at <http://www.cs.man.ac.uk/fellowsd-bin/TIP/19.patch> |
Name change from tip/190.tip to tip/190.md.
|
| < | < | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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 | # TIP 190: Implementation Choices for Tcl Modules Author: Andreas Kupries <[email protected]> Author: Jean-Claude Wippler <[email protected]> Author: Jeff Hobbs <[email protected]> State: Draft Type: Informative Vote: Pending Created: 24-Mar-2004 Post-History: ----- # Abstract This document is an informational adjunct to [[189]](189.md) "Tcl Modules", describing a number of choices for the implementation of Tcl Modules, pure-Tcl, binary, or mixed. It lists these choices and then discusses their relative merits and problems, especially their interaction with wrapping, i.e. when used in a wrapped application. The main point of the document is to dispel the illusion that the restriction to the "source" command for the loading Tcl Modules is an actual limitation. A secondary point is to make recommendations regarding preferred implementations, based the merits and weaknesses of the various possibilities. # Implementation Choices A small recap first: Tcl Modules are Packages in a single file, and only **source** is used to import them into the running interpreter. These restrictions are the backdrop to all implementations discussed here. ## Packages Written in Tcl These are easy. * A package which is implemented in a single file is already in the form required for a Tcl Module and nothing has to be done at all. +--------------+ | Tcl File | +--------------+ > Most packages in Tcllib<http://tcllib.sf.net> can be of this form. * In the case of a package whose implementation is spread over multiple .tcl files the solution is equally simple. Just concatenate all the files into one file when generating the distribution. This is a trivial operation. +--------------++--------------+...+--------------+ | Tcl File 1 Tcl File 2 Tcl File n | +--------------++--------------+...+--------------+ > Some packages in Tcllib<http://tcllib.sf.net> can be of this form, or rewritten into it. * The usage of an compiler/obfuscater like TclPro/Tcl Dev Kit on such Tcl Modules is also no problem. While the result of these compilers contains binary, it is in encoded form, and the file is still a proper Tcl script which can be handled by **source**. The encoded binary is decoded by an adjunct package, **tbcload**, whose import is the first action done by the script. > This also points us already to the general solution for binary packages, i.e. usage of supporting packages to handle arbitrary data embedded or attached in some way in/to an initialization script. The usage of pure-Tcl Modules within wrapped applications poses no problems at all. Also note that all of the choices available to binary packages, as explained in the next section, are available to pure-Tcl packages as well. # Binary Packages A binary package consists of a shared library, possibly with adjunct Tcl and data files. These have to be bundled into a single file to be a Tcl Module. The general approach to this is to combine an init script written in Tcl with binary data attached to it, both sections separated by a ^Z character. This is possible since 8.4, where **source** was changed to read only up to the first ^Z and ignore the remainder of the file, whereas other **file** and channel operations will see it. ## Embedding a Virtual Filesystem The most obvious way of doing this is the any-kit approach: a small initialization script in front which loads all required supporting packages and then uses them to mount an attached virtual filesystem containing all the other files. After the mount any package specific initialization can be performed, either in the initialization script itself, or in a separate script file stored in filesystem. The latter is the recommended form as it keeps the main initialization script small and package neutral i.e. it will be only filesystem specific, and not package specific. These two tasks are kept separate, which is good design in general, and becomes more important later on as well. +-------------||------------------------------------+ | Init header ^Z VFS +------------+ +-----...-----+ | | ^Z | Shared lib | | Other files | | | ^Z +------------+ +-----...-----+ | +-------------||------------------------------------+ A concrete example of this are starkits, except that they use this technique to wrap an application into a single file, and not a package. When interacting with wrapping this approach runs into problems. It is not possible to simply copy the module file into the wrapped application and then use it. The problem is a limitation in most implementations of alternate filesystem: they are not able to mount a virtual file again as a directory, i.e. _nested_ mounting. This however is required when a Tcl Module using the any-kit approach is placed into a wrapped application. It was thought for a while that this could be a limitation in the VFS core of Tcl itself, but further investigation proved this to be wrong. This proof came in the form of TROFS, the _Tcl Read Only Filesystem_, by Don Porter. This filesystem supports nesting and thus shows that the Tcl core is strong enough for this as well. It is the implementation of a filesystem which determines if nesting is possible or not, and most do not support this. See also SF bug report _[[941872]](941872.md) path<->FS function limitations_ <http://sf.net/tracker/?func=detail&aid=941872&group_id=10894&atid=110894> for more details on this and other problems. There are two ways to work around this limitation, while it exists. These are explained below. However note that even if the limitation is removed we may still run into performance problems because of a file accessed through several layers of file systems, each with its own overhead. The workarounds we are about to discuss will help with |
︙ | ︙ | |||
142 143 144 145 146 147 148 | the necessary scripts, like "pkgIndex.tcl". Here the separation of filesystem specific from package specific initialization comes into play as well as it makes the unbundling much easier. The generated package index file can simply refer to the same package initialization script as the filesystem specific header of the bundled module. | | | | | | | | | | | | | | | | | > | 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 | the necessary scripts, like "pkgIndex.tcl". Here the separation of filesystem specific from package specific initialization comes into play as well as it makes the unbundling much easier. The generated package index file can simply refer to the same package initialization script as the filesystem specific header of the bundled module. > It should be noted that unbundling is limited to the filesystems which are recognized by the wrapper application. Because of this a combination of this and the previous approach might be best, as it allows the module to function even if the wrapper application was not able to unbundle it. More a problem of taste might be that Tcl Modules in this form require additional packages which implement the filesystem they use. This can be remedied in the future by adding additional reflection capabilities to the Tcl core which would allow the implementation of channel drivers, channels transformations, and filesystems in pure Tcl, and then implementing simple filesystems based on that. This would also allow the Tcl core itself to make use of filesystems attached to its shared libraries and executables. ## Appending a Shared Library Should the binary package consist of only one shared library we can forgo the use of a full-blown virtual filesystem and simply attach the shared library to the init script as is. Instead of mounting anything the init script just has to copy the library to a temporary place and then "load" it. +------------------------------||----------------+ | Init script (p name, p size) ^Z Shared library | +------------------------------||----------------+ Tcl Modules implemented in this way will have no problems when used in a wrapped application as they will always copy their relevant file to the native filesystem before using it. The disadvantage is that this is not a very general scheme. There are not that much packages which consist of only one shared library and nothing else. Note: Should we ever get loading of a shared library directly from memory or from a location in another file, then copying the library to the filesystem won't be necessary anymore either. ## Appending a Library and a VFS An extension of the last approach is to attach the virtual file system not to the init script, but the shared library. +-------------||----------------++---------------------+ | Init script ^Z Shared library // VFS +-----...-----+ | | ^Z // | Other files | | | ^Z // +-----...-----+ | +-------------||----------------++---------------------+ This approach has the same advantages as the last with regard to its interaction with wrapping, i.e no problems, and additionally handles additional files coming with the shared library. The initialization of the VFS happens in the init script, but after the shared library has been loaded. I have to admit that I am not sure if this will truly work. In essence the library will have to be told about the directory for its files after its C level initialization has been run. If the VFS is required during the C level initialization then the VFS has to be initialized and mounted from within the shared library, i.e. at the C level. This is not very convenient as we need an embedded Tcl script for this, and that makes the code of the library more complicated than required. # Recommendations We currently recommend usage of the any-kit approach for binary packages, despite its problem with nested mounting. This approach has an existing implementation in the metakit-based starkits and is thus well tested in general. The other two approaches are currently purely theoretical, with neither any implementation, nor testing. Regarding Tcl packages no recommendation is necessary as we have in essence only one possibility for the more complex case, the simple concatenation of multiple files into a single one. # Questions # Comments [ Add comments on the document here ] # Copyright This document has been placed in the public domain. |
Name change from tip/191.tip to tip/191.md.
|
| < | < | | | | | | | | > | | | | | 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 | # TIP 191: Managing Tcl Packages and Modules in a Multi-Version Environment Author: Andreas Kupries <[email protected]> Author: Joe English <[email protected]> Author: Larry Virden <[email protected]> State: Draft Type: Informative Vote: Pending Created: 24-Mar-2004 Post-History: ----- # Abstract This document is an informational adjunct to [[189]](189.md) "Tcl Modules", describing a number of choices for the management of Tcl Modules in environments with more than one version of the Tcl core installed. It lists these choices and then discusses their relative merits and problems. # Background and Motivation A regular package can perform checks in its "pkgIndex.tcl" file regarding the environment the package would be loaded into should it be requested, and make the creation of its "provide script" dependent on the result. In other words, it is able to prevent its registration, making it invisible to the Tcl interpreter in question if the environment is not right \(for example, if the interpreter is too old a version of Tcl\). A Tcl module cannot do this as its "provide script" is generated by the module system. In a controlled environment, like wrapped applications of any form this is a complete non-issue as we can assume that only those modules are installed which are not only required, but needed. |
︙ | ︙ | |||
48 49 50 51 52 53 54 | version may not work anymore with the new version, or a different version of the package has to be selected from among the installed versions. This situation can be viewed as having multiple version of Tcl, however over time instead of space. For the environments with multiple versions of Tcl in space a number of possible solutions are explained in the next section. | | | | | | | | | | > | 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 | version may not work anymore with the new version, or a different version of the package has to be selected from among the installed versions. This situation can be viewed as having multiple version of Tcl, however over time instead of space. For the environments with multiple versions of Tcl in space a number of possible solutions are explained in the next section. # Choices All solutions are done outside of the Tcl interpreter, in the filesystem. * Each interpreter has its own part of the filesystem. Modules required in several of them are copied around. Modules not required are not copied. This is easy. It requires more disk space; however that is cheap. * Same as above, but use hard- and/or soft-links instead of copying. Modules not eligible somewhere are not linked. > This schema can also be used to maintain a central repository, which is just a directory tree containing all module files in their proper locations. Then link the packages which should be visible to an interpreter into their respective directory trees. > This makes the creation of test environments with a known set of packages very easy as well. * Keep the modules in several directory trees as wanted and/or needed by sharing requirements and then set the list of search paths used by an interpreter to exactly those trees which have the modules required/usable by it. ## Changes over Time Note that the default paths set down in [[189]](189.md) ease the management, as each Tcl shell will not only have its own space, but also access to extensions for all minor versions which came before it. This means that placing an extension into the directory for the smallest version of Tcl supporting it will make this extension available to this minor version and all the versions which come after and share the major version. This is the right thing almost all of the time. Only extensions using internal interfaces will have to be dealt with separately. # Questions # Comments [ Add comments on the document here ] According to Don Porter the given solutions will not scale. # Copyright This document has been placed in the public domain. |
Name change from tip/192.tip to tip/192.md.
|
| < | < | | | | | | | | | > | | | | | | | | | | | | < > | < | | > | | | | < > | | | | | | | | | | < > | | < | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 192: Lazy Lists Author: Salvatore Sanfilippo <[email protected]> Author: Theo Verelst <[email protected]> State: Draft Type: Project Vote: Pending Created: 27-Mar-2004 Post-History: Keywords: Tcl Tcl-Version: 9.0 ----- # Abstract This TIP proposes to add a new command to generate lists of _N_ elements, where the _i_-th element is computed as the result of an unary Tcl procedure with _i_ as itsargument. Implementing special handling for this kind of lists inside the Tcl core will allow generation of lists in a _lazy_ way. This TIP's goal is not to change the semantics of Tcl, but just to provide a different space complexity for an \(often interesting\) subset of Tcl lists. # Rationale A subset of Tcl lists can be generated mapping an unary function to an integer sequence in the range [0,n\), where _n_ is the length of the list. The following procedure implements this concept: proc lgen {len func} { set l {} for {set i 0} {$i < $len} {incr i} { lappend l [uplevel 1 [list $func $i]] } return $l } and the following \(using the **lambda** from [[187]](187.md)\) is an example of usage: proc lambda {argl body} { set name [info level 0] proc $name $argl $body set name } set mylist [lgen 10 [lambda x {incr x; expr $x*$x}]] The above code will evaluate to the same as [list 1 4 9 16 25 36 49 64 81 100]. **lgen** can be used in order to build a particularly useful Tcl procedure named **range**, returning a sequence of integers with given _start_ _end_ and \(optionally\) _step_ paramenters. The **range** function is convenient for rewriting many **for** loops in terms of **foreach** iterating over an integer range. So instead of writing: for {set i 0} {$i < 20} {incr i 2} { puts $i } It is possible to write: foreach i [range 0 20 2] { puts $i } That is more convenient to write and to read for the programmer. Of course it's possible to use **foreach** to iterate any sequence that **lgen** is able to generate, but **range** is probably one of the more common of the possible usages. The TIP proposes to implement the ability to handle this kind of lists in a special way directly inside the _List_ object implementation. This allows these common usage patterns of the list object to not need to hold the real sequence but just the length and the unary element generator function. The interface to the Tcl programmer is a single command similar in semantics to **lgen**, but possibly with a more suitable name. # Proposed Change The _List_ object should be modified in order to have the lazy-list as subtype or alternate internal implementation. All the core should use the proper _List_ object API instead to access to the _List_ object via the internal representation. The two calls that should be guaranteed to not alter the _lazyness_ of the list are **Tcl\_ListObjLength\(\)** and **Tcl\_ListObjIndex\(\)**. Other calls like **Tcl\_ListObjReplace\(\)** may be optimized for the lazy-list case when possible, and the **lrange** command may be optimized \(particularly when the start index is zero\). The _List_ will be converted into a non-lazy version if the user tries to modify it, for example using the **Tcl\_ListObjAppendElement\(\)** function. The _List_ will also be converted into a non-lazy version on **Tcl\_ListObjGetElements\(\)** calls. It's possible to handle the **range** command as a particular case of lazy-list in order to provide a very fast implementation of foreach iterating over an integer range \(probably much faster than the today **for**, being **foreach** already faster iterating over a literal list of numbers\). ## Consequences: Reference Management The author of this TIP tried to implement the proposed changes in the HEAD, discovering that the **Tcl\_ListObjIndex\(\)** interface creates a serious problem due to the assumption that the _List_ object holds at least one reference to the returned element. The implementation of **Tcl\_ListObjIndex\(\)** in the lazy case can't just create the element object and return it with refcount of zero because it will leak if the caller does not increment the reference count itself. It's also not safe to store a reference to the last few elements created in the lazy way inside the _List_ object, and release this references in order to create more elements, because in theory the caller may require a large number of elements storing pointers into an array, and finally incrementing the reference counts in a single pass. In order to avoid this problem, the semantics of **Tcl\_ListObjIndex\(\)** should be changed in order to always return the element with an already incremented reference count. It will be up to the caller to decrement the reference count if the object will be discarded. \(This is why this change is proposed for Tcl 9.0 and not 8.5, as this has a significant impact on both the core and on extensions.\) An alternative change to **Tcl\_ListObjIndex\(\)** \(in order to make it "compatible" with the semantics of lazy lists\) is to disallow successive calls against the same list if a previous call returned an object that the caller plans to reference the object. So: Tcl_ListObjIndex(interp, myListPtr, 0, &a); Tcl_ListObjIndex(interp, myListPtr, 0, &b); mystruct->a = a; mystruct->b = b; Tcl_IncrRefCount(a); Tcl_IncrRefCount(b); will be invalid, while: Tcl_ListObjIndex(interp, myListPtr, 0, &a); Tcl_IncrRefCount(a); mystruct->a = a; Tcl_ListObjIndex(interp, myListPtr, 0, &b); Tcl_IncrRefCount(b); mystruct->b = b; is valid. This fixes any problem because the _List_ object can just take a reference to the last generated object and avoid any leak. A study of existing code in the core and extensions is required to see whether this will allow the majority of code to operate unchanged. ## Consequences: Non-constant Lists The TIP also poses another problem in the case the unary function has side effects. In this case the behaviour can be described without to violate the Tcl semantic in terms of variable traces most of the time, but actually it's possible to write code that shows that the list value is non-stable even without using variables \(because Tcl has no "object trace" concept actually\). If this is considered a problem, the TIP may be reduced in order to only allow lazy generated lists composed of integer ranges, \(but that is one of the most interesting advantages of this TIP anyway.\) With integer ranges there are no side effects, so the semantical problem is not an issue, but the **Tcl\_ListObjIndex\(\)** problem is exactly the same. Of course, this is arguably just an unavoidable consequence and shows that not all possible unary element generator functions, but just those with a functional denotation, are necessarily reasonable choices. # Copyright This document has been placed in the public domain. |
Name change from tip/193.tip to tip/193.md.
|
| < | | | | | | < | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 193: Simple Syntax Help System State: Draft Type: Project Tcl-Version: 8.7 Vote: Pending Post-History: Author: Donal K. Fellows <[email protected]> Created: 29-Apr-2004 Keywords: Tcl ----- # Abstract This TIP proposes a simple scheme to allow commands to provide basic syntax help for themselves. This information would allow for more advanced processing by programs doing interactive input of Tcl commands \(by providing a mechanism for them to discover what possible completions of the current command fragment are available\) and could be processed automatically by the **interp alias** and **namespace ensemble** mechanisms so that help could be automatically extended to commands defined through those mechanisms. # Rationale Currently, Tcl commands are only partially consistent in how they provide information about their own syntax; the only way of getting any syntax help is by providing invalid input to the command, but not all commands have invalid input sequences \(e.g. **list**\) and nor is there any way of knowing what those invalid sequences are \(where they do exist\) unless you know the command beforehand. Such help would be useful in a number of situations, such as command expansion in something like tkcon. It would also provide a mechanism for supplying the sort of detailed information which the likes of [incr Tcl]'s ensembles can generate, but which the Tcl ensembles of [[112]](112.md) do not do \(for the reason that this would produce output significantly different in kind from existing core commands.\) Note that I do not want to provide extended help such as might be obtained from manual pages; this help system is designed to be mechanically queryable first. # Proposed Change There are two main components ## Data Model Every command would supply help for itself by providing a callback to generate the information on demand; there will be a compatability callback installed by default that states that the command may take any number of unknown arguments. The result of the callback will be a list of command call descriptions. Each description will be itself a list of terms that describe a particular way of calling the command, with one term per argument. Each term may in turn be one of: * _Required literal_ - this might be something like a subcommand name. * _Optional literal_ - a good example of this are the **then** and **else** words in a call to **if**. * _Required varying_ \(with name for display to the user\) - a normal argument which may be whatever the caller wants it to be, subject to the higher level constraints implicit in the name. * _Optional varying_ \(with name for display to the user\) - a normal optional argument. * _All remaining arguments_ - this would be used in the default help outlined above, but would also be useful for modelling the _args_ parameter to a procedure. [ToDo: say how these are expressed in C code] [ToDo: talk about how aliases and ensembles can do help construction] [ToDo: talk about how such information can be partially derived in procedures] ## Information Access There will be a new subcommand of **info** to provide access to this information at the Tcl level: **help**. The first argument to **info help** will be the name of a command; if no further arguments are supplied, the result will be a multi-line string with one invokation per line; the invokations will be just the string parts with the literal/varying information omitted and the optional/required information converted into surrounding question marks. Otherwise, the second argument to **info help** will be one of: get: Two optional arguments; an index into the list of help "lines" \(first\) and an index within the line \(second\). If one index is supplied, returns the list of values \(without lit/var or opt/req info\) for the indexed line. If two indexes are supplied, returns the string form for the indexed word within the indexed line. If no indexes are supplied, or returns a list of every such value list when no index is supplied. literal: Two required arguments; an index into the list of help "lines" and an index into the list of values for that line. Returns a boolean that is true when the indexed word within the indexed line is a literal. required: Two required arguments; an index into the list of help "lines" and an index into the list of values for that line. Returns a boolean that is true when the indexed word within the indexed line is required. [ToDo: could **info help** be used as a mechanism for procedures to set their own help up?] # Copyright This document has been placed in the public domain. |
Name change from tip/194.tip to tip/194.md.
|
| < | < | | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | < > | | | | < > | | | < | > | | | | | | | | | | | | | | | | < > | | | < > | | | | | | | | | | | | | | > | 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 | # TIP 194: Procedures as Values via '''apply''' Author: Miguel Sofer <[email protected]> Author: Joe Mistachkin <[email protected]> State: Final Type: Project Vote: Done Created: 30-Apr-2004 Post-History: Keywords: Tcl,lambda,anonymous,command,function,functional programming Tcl-Version: 8.5 ----- # Abstract This TIP proposes a new command, tentatively named **apply**, to allow procedures to be first class values. It is an alternative to the approach of [[187]](187.md), where attaining a similar goal requires a syntactic and semantic change. # Rationale Tcl is typeless, and every first class value is a string \(or at least representable as such\). Strings are managed by reference counting in the Tcl core, the required memory is freed automatically when the string is no longer referenced. Tcl commands may interpret their arguments differently. Some commands interpret some of their arguments as scripts - **eval**, **uplevel**, and so on. But no current Tcl command is able to specify that a script is to be run in an isolated environment, free of unwanted side effects or memory leaks caused by name collisions. In order to achieve this isolation, one has to define a new command via **proc** and assume the burden of name-collision avoidance and lifetime management, or else produce complicated scripts with ugly contorsions to avoid the name collisions. Both [[187]](187.md) and this one propose ways to provide this lacking functionality to Tcl. The approach here is to do so by creating a new **apply** command without any change to Tcl's syntax. # Specification A reference manual page can be found at <http://utdt.edu/~mig/apply2.html> . Summarizing, the syntax of the new command is: * **apply** _func_ ?_arg1 arg2 ..._? > The first argument _func_ is an anonymous function - a list of two or three elements [**list** _arglist body_ ?_namespace_?]. The first two are exactly like the arguments to **proc**, the third determines the namespace for **variable**, **namespace** and command resolution when the body is evaluated. The _namespace_ is interpreted as fixed, and is the interpreter's global namespace in the two-argument case. > The remaining arguments _arg1 arg2 ..._ are taken as values for the first formal arguments in _arglist_. The semantics of **apply** \(with the exception of some of the fine details of error messages\) can be described by: proc apply {fun args} { set len [llength $fun] if {($len < 2) || ($len > 3)} { error "can't interpret \"$fun\" as anonymous function" } lassign $fun argList body ns set name ::$ns::[getGloballyUniqueName] set body0 { rename [lindex [info level 0] 0] {} } proc $name $argList ${body0}$body set code [catch {uplevel 1 $name $args} res opt] return -options $opt $res } where the availability of a **getGloballyUniqueName** procedure was assumed. # Reference Implementation There is a patch <http://sf.net/tracker/?func=detail&aid=944803&group_id=10894&atid=360894> that implements this TIP. The patch defines a new _tclLambdaType_ for _Tcl\_Obj_s that caches the internal structures necessary for efficient evaluation: a Proc struct, a pointer to _namespace_, and the bytecodes implementing _body_. It is a small patch that relies heavily on the implementation of **proc**, producing essentially a regular **proc** with no command attached to it: an anonymous function. All cached internal structures are freed when _func_ ceases to be referenced or when it loses its internal representation as a _tcllambdaType_ through shimmering. Note that a similar approach is likely for a definitive implementation of [[187]](187.md). # Further Functional Programming Constructs The availability of **apply** permits an easy and efficient access to other FP functions. For example one might define a constructor **lambda** and a **curry** command like this: proc lambda {arglist body {ns {}}} { list ::apply [list $arglist $body $ns] } proc curry {lam args} { lappend lam {expand}$args } Function composition is also relatively easy to specify. Further examples may be seen in the Wiki, see for instance Neil Madden's **map**, **filter**, **foldl**, **foldr** <http://wiki.tcl.tk/11141> - note that the syntax is slightly different from the one proposed here. # Comparison to TIP 187 and outlook In terms of usage, the main difference is that where TIP 187 does: set p [list lambda x {string length $x}] $p $foo we would do here: set p [list ::apply [list x {string length $x}]] # or: set p [lambda x {string length $x}] {expand}$p $foo ;# or 'eval $p [list $foo]', or ... or else: set p [list x {string length $x}] apply $p $foo This TIP requires no changes to the rules in Tcl\(n\), whereas [[187]](187.md) requires a change in rule [[2]](2.md). If in the future Tcl evolves a rule for automatic expansion of leading words, **apply** will provide automatically the syntax of [[187]](187.md). # Copyright This document has been placed in the public domain. |
Name change from tip/195.tip to tip/195.md.
|
| < | < | | | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | < | > | | | | | < | > | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 195: A Unique Prefix Handling Command Author: Peter Spjuth <[email protected]> Author: Peter Spjuth <[email protected]> State: Final Type: Project Vote: Done Created: 02-May-2004 Post-History: Keywords: Tcl Obsoletes: 105 Tcl-Version: 8.6 ----- # Abstract This TIP adds a new command to support matching of strings to unique prefixes of patterns, similar to Tcl's existing subcommand-name matching or Tk's option-name matching. # Rationale When code \(particularly in script libraries\) wants to support shortest unique prefix matching in the manner of the Tcl core \(as provided by _Tcl\_GetIndexFromObj_\) currently either the prefixes have to be precomputed \(by hand or by script\) or the matching has to be done backwards. In the first case, this is either error-prone or requires an extra piece of code that has to be developed by the programmer. In the second case, the code has to be converted into a pattern which is matched against the list of supported options in some way, which is either inefficient or has hazards if the string being matched contains characters that are meaningful to the matching engine being used. Instead, it would be far nicer if we could make the core support this directly, so that script authors could just say what they mean. See also [[105]](105.md), which the text above comes from. Another benefit of this command is getting an error message that looks like those nice and informative error messages that built in commands have. The proposed command includes a flag to control the error behaviour. Another use of prefix matching is for completion, such as a combobox showing matching alternatives, or tab completion at a prompt. The former needs a list of matching elements, and the latter needs a longest common prefix. These functionalities are similiar enough to group them but different enought to make it a bad idea for flags, so a prefix ensemble seems approriate for them. # Proposed Change To support this, I propose adding a **::tcl::prefix** ensemble with the following subcommands * **prefix** **match** ?**-exact**? ?**-message** _string_? ?**-error** _options_? _list_ _string_ * **prefix** **longest** _list_ _string_ * **prefix** **all** _list_ _string_ All commands are given a list of possibilities and a string to match. **prefix** **match** returns the matching element in the list or an error. Basically it does what _Tcl\_GetIndexFromObj_ does except it returns a string instead of an index. The options **-exact** and **-message** corresponds to the _flags_ and _msg_ arguments to _Tcl\_GetIndexFromObj_. The default value for **-message** is "option". The **-error** options are used when no match is found. If **-error** is empty, no error is generated and an empty string is returned. Otherwise the options are used as **return** options when generating the error message. The default corresponds to setting "-level 0". Example: If **-error** "-errorcode MyError -level 1" is used, an error would be generated as [return -errorcode MyError -level 1 -code error "ErrMsg"]. **prefix** **longest** returns the longest common prefix within the group that matches the given string. If there is no match, an empty string is returned. **prefix** **all** returns a list of all matching elements. # Examples Basic use: % namespace import ::tcl::prefix % prefix match {apa bepa cepa} apa apa % prefix match {apa bepa cepa} a apa % prefix match -exact {apa bepa cepa} a bad option "a": must be apa, bepa, or cepa % prefix match -message "switch" {apa ada bepa cepa} a ambiguous switch "a": must be apa, ada, bepa, or cepa % prefix longest {fblocked fconfigure fcopy file fileevent flush} fc fco % prefix all {fblocked fconfigure fcopy file fileevent flush} fc fconfigure fcopy Simplifying option matching: array set opts {-apa 1 -bepa "" -cepa 0} foreach {arg val} $args { set opts([prefix match {-apa -bepa -cepa} $arg]) $val } Switch similar to [[105]](105.md): switch -- [prefix match {apa bepa cepa} $arg] { apa { } bepa { } cepa { } } # Alternative names Alternative names for the command that have been suggested are **prefix**, **string prefix**, **string disambiguate**, **string prefixmatch**, **string matchprefix** and **lsearch -prefix**. Any name based on _Tcl\_GetIndexFromObj_ feels wrong since this command does not get any index. # Discussion Pascal Scheffers wrote: I am not very fond of new toplevel commands, as they have a habit of breaking existing code, or, more likely, being redefined by existing code. How about **string prefix ...** or **lsearch -prefix**? It feels like something that could logically reside inside string handling or list handling. Donal Fellows wrote: Hmm, a new matching style for **lsearch** could work \(yet another option for an overly scary command!\) especially in conjunction with some of the other options like -inline, but I suspect it'll have to be **string prefix** or something like that since then we can easily state that the behaviour is not to necessarily return the first matching element. That was what scuppered \#105 after all \(much to my annoyance.\) Peter Spjuth: TIP was at this point altered to suggest **string disambiguate** after a suggestion from Donal. Donal Fellows wrote: I'd suggest that the **-exact** option be dropped, as it is trivially implementable using **lsearch -exact**, **dict exists**, **info exists**, **switch**, etc. It's also corresponding to a very rarely used flag to Tcl\_GetIndexFromObj. Peter Spjuth: Other ways to do **-exact** doesn't give the standardized error message so it has some value for those that want that functionality. The Core uses TCL\_EXACT in a few places where it makes sense so the flag can be useful. Voices were raised against the proposed **string disambiguate** and Jeff Hobbs pointed out other prefix related functions that are useful. This lead to the prefix ensemble suggestion. # Reference Implementation Partial implementation at: <https://sourceforge.net/support/tracker.php?aid=1040206> # Copyright This document has been placed in the public domain. |
Name change from tip/196.tip to tip/196.md.
|
| < | < | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | < < < > > > | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 196: Tcl Commands as Values Author: Robert Suetterlin <[email protected]> State: Withdrawn Type: Project Tcl-Version: 8.5 Vote: Pending Created: 11-May-2004 Post-History: ----- # Abstract This TIP proposes making command procedures first-class values in Tcl. It also changes the command binding scheme to recognize these values before performing old-style name lookup indirection. # Rationale A Tcl script is a string containing one or more commands separated by semicolons or newlines. The evaluation of the script breaks these commands into words. Currently the string value of the first such word is used to lookup a command procedure \(effectively a function pointer\) and some clientData \(per-command instance state\). These will then be used by the virtual machine. For example, in the case of pure Tcl procedures created with **proc** command, this is _TclProcInterpProc_ with an associated _procPtr_ that basically references the procedure body \(as a string\) and its formal argument list. Because of the name lookup indirection, Tcl does not support anonymous commands. \(There is quite some interest in using such with Tcl, please compare [[187]](187.md) and [[194]](194.md). Several other languages \(even C\) support anonymous commands. They seem to be quite useful, just compare their use in Tcl's C code.\) This can be changed by allowing for a new kind of word \(i.e. a new **Tcl\_Obj** _commandObject_\) that can be immediately interpreted as a command. \([[187]](187.md) proposes the use of special Tcl lists, but this is too limiting for the scope of this document.\) The evaluation checks if the first word is a _commandObject_, if not it does the old style name lookup \(with **unknown** fallback\). A _commandObject_ should store information equivalent to what is provided with the **Tcl\_CreateCommand\(\)** API and stored in the global name lookup table. Thus it can reference any command procedure and any clientData, allowing the creation of arbitrary anonymous commands in C extensions for example. Having such _commandObject_s available will allow for **proc** to return these instead of an empty string and to skip registration of a command when its name is provided as the empty string. # Examples This will allow to reproduce all of the features of [[187]](187.md). Compare this example with the one in [[187]](187.md): proc filter {list proc} { set res {} foreach e $list { if {![$proc $e]} { lappend res $e } } } set a [list 1 10 100 4 5] set b [filter $a [proc x {expr $x<10}]] This sets the variable b to the list \{_10 100_\}. In addition this TIP still allows: proc {list lambda x {body}} {var} {puts $var} if we really want to. And we can use _commandObject_s that have not been created by **proc** in the first place - think OOP for example. These _commandObject_s could also be used as data structure for the command namespace, which would then become a dictionary, if I recall correctly. Allowing for registering an anonymous command with a name \(via **rename**\) by putting the name and the commandObject into the dictionary. # Specification This document proposes at least the following changes to the Tcl core: 1. Include a new _Tcl\_Obj_ **commandObj** that contains information equivalent to the arguments _proc_, _clientData_ and _deleteProc_ to **Tcl\_CreateObjCommand\(\)**. \(Maybe interp is necessary, too. But I don't understand the byte compiler and execute stuff good enough to judge.\) 2. Change **Tcl\_GetCommandFromObj\(\)** to check if _objPtr_ references a _commandObj_ first, otherwise check if it finds a named command. 3. Have the **proc** command return a _commandObj_ that is equivalent to the **Tcl\_Create\(Obj\)Command\(\)** calls in **Tcl\_ProcObjCmd\(\)**. i.e. the _proc_ is equal to **Tcl\(Obj\)InterpProc\(\)** and the _clientData_ is the _procPtr_. # Copyright This document is in the public domain. |
Name change from tip/197.tip to tip/197.md.
|
| < | < | | | | | | | | | > | | | | | | | | | | > | 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 | # TIP 197: Unfocussed Text Widget Cursor Control Author: R. Timothy Edwards <[email protected]> Author: Donal K. Fellows <[email protected]> State: Final Type: Project Tcl-Version: 8.6 Vote: Done Created: 12-May-2004 Post-History: Keywords: Tk ----- # Abstract This TIP proposes a simple extension to the Tk text widget to allow the insertion cursor to persist when the window containing the text widget does not have focus. # Rationale In some cases it is useful to redirect text from one top-level window into a separate top-level window containing a text widget. In such a case, it is helpful to be able to see the cursor in the text widget. However, as implemented, the Tk text widget always erases the insert cursor when the window loses focus. It is a trivial fix to add an option **-insertunfocussed** to the text widget that keeps the text cursor in the window. # Specification The extension would provide a global **text** widget option **-insertunfocussed** with a ternary value. The current behaviour would be the default. > _pathName_ **configure -insertunfocussed** _value_ Supported values will be: none: Do not display the insertion cursor when the text widget doesn't have the focus. hollow: Display the border of the insertion cursor when the text widget doesn't have the focus, but do not fill the cursor or make it flash. If the **-insertborderwidth** option is zero, draw \(but do not fill\) a rectangle in the **-insertbackground** color. solid: Display the insertion cursor unchanged whether or not the text widget has the focus. The insertion cursor will not flash when the widget does not have the focus. In all cases, the insertion cursor will be displayed as at present when the text widget does have the focus. # Copyright This document has been placed in the public domain. |
Name change from tip/198.tip to tip/198.md.
|
| < | < | | | | | | | | | > | | | | | | | | | | | | | > | 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 | # TIP 198: Image Command XPM Extension Author: R. Timothy Edwards <[email protected]> Author: Don Porter <[email protected]> Author: Kevin Kenny <[email protected]> State: Draft Type: Project Vote: Pending Created: 12-May-2004 Post-History: Tcl-Version: 8.7 ----- # Abstract This TIP proposes an extension to the Tk **image** command to incorporate color pixmap images based on the XPM format. The format is analogous to the **bitmap** option \(_tkImgBmap.c_ in the Tk source\). # Rationale The "XPM" format has become more-or-less a standard, and is a nice text-readable color alternative to the standard X11 bitmap format. The runtime library for XPM is available in standard Linux distributions and elsewhere. Tk has a number of color **photo** image formats, but these make various assumptions about rendering. There is no color alternative to the simple pixel-based bitmap format. # Specification This TIP specifies the extension of the **image** command in the following manner: > **image create xpm** _name_ **-file** _xpm\_file_ It would probably be a nice idea to include in-line pixmap specifications similar to that allowed for bitmaps by the BLT package. However, at this time, the reference implementation does not include such an extension. # Reference Implementation There is an implementation in the source for XCircuit<http://xcircuit.ece.jhu.edu/> . The source file is "tkPixmap.c". # Comments I'd like to see more justification in this proposal as to why a new image type is needed, rather than implementing a suitable format for either the existing bitmap or photo image types. In fact, the Img extension already has XPM as a photo image format. I'm quite baffled as to the need for a new image type. Is this TIP better served by a request to promote XPM to the core set of supported formats? # Copyright This document has been placed in the public domain. |
Name change from tip/199.tip to tip/199.md.
|
| < | < | | | | | | | | | > | | | | | | | | | | | | > | 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 | # TIP 199: Specification of Alternatives to .wishrc/.tclshrc Author: R. Timothy Edwards <[email protected]> Author: Don Porter <[email protected]> State: Rejected Type: Project Vote: Done Created: 12-May-2004 Post-History: Keywords: Tcl,Tk,shell,interactive Tcl-Version: 8.6 ----- # Abstract This TIP describes an extension of the command-line options to the "wish" and "tclsh" programs to allow the startup script to be redirected from the default ~/.wishrc \(or ~/.tclshrc\) to an alternative file. # Rationale It is possible to run an application from a terminal that starts up a GUI or other event-based process but that, after setting up the event callback procedures, drops back into the terminal to allow a dual-input interface. As written, the only way to execute a script and return to the interpreter prompt in the terminal is to put the script in the ".wishrc" or ".tclshrc" startup script. One has to bend over backwards to write an application that will make this happen without actually changing the user's startup scripts. The shell script must redefine environment variable _$HOME_ to point to the place where the script is that needs to be run, and the script itself then must be named ".wishrc" or ".tclshrc", or must have a symbolic link of that name pointing to it. The _$HOME_ environment variable must be copied to another variable name if the application needs to reference the original value. All this can be avoided by simply having a shell command-line option "**-startup** _filename_" that allows the specification of a name other than ".wishrc" or ".tclshrc" in a directory path that is not necessarily the user's home directory, to be used as the startup script. This would not only be useful for the purpose outlined above, but also to simply bypass whatever commands are executed by the default startup script. # Specification The command-line option for "wish" and "tclsh" would be extended to add the option **-startup**, for example: > **wish -startup** _filename_ [_other options_] # Comments You are seeking interactivity following the evaluation of a start-up script. Is that the whole point? If so, then an alternative solution is provided at Tcl Patch 955470. <http://sf.net/tracker/index.php?func=detail&aid=955470&group\_id=10894&atid=310894> # Copyright This document has been placed in the public domain. |
Name change from tip/2.tip to tip/2.md.
|
| < | < | | | | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 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 | # TIP 2: TIP Guidelines Author: Andreas Kupries <[email protected]> Author: Donal K. Fellows <[email protected]> Author: Don Porter <[email protected]> Author: Mo DeJong <[email protected]> Author: Larry W. Virden <[email protected]> Author: Kevin Kenny <[email protected]> State: Draft Type: Process Vote: Pending Created: 12-Sep-2000 Post-History: ----- # Abstract This document describes and defines the editorial process a TCT document \(TIP\) has to go through before accepted as official. # What is a TIP? TIP stands for Tcl Improvement Proposal. A TIP is a design document providing information to the Tcl community, or describing a new feature for Tcl. The TIP should provide a concise technical specification of the feature and a rationale for the feature. We intend TIPs to be the primary mechanisms for proposing new features, for collecting community input on an issue, and for documenting the design decisions that have gone into Tcl. The TIP author is responsible for building consensus within the community and documenting dissenting opinions. Because the TIPs are maintained as text files under revision control, their history is the historical record of the feature proposal. This historical record is available by the normal \(CVS?\) commands for retrieving older revisions. For those without direct access to the CVS tree, you can browse the current and past TIP revisions <http://www.cs.man.ac.uk/fellowsd-bin/TIP/> . Further details on the arguments behind the evolution of the TIP concept and formatting can be found in the archive of the _tclcore_ mailing list <http://aspn.activestate.com/ASPN/Mail/Browse/Threaded/tcl-core> . # Kinds of TIPs There are three kinds of TIPs. A project TIP describes a new \(or significantly updated\) feature or implementation for Tcl. An informative TIP describes a Tcl design issue, or provides general guidelines or information to the Tcl community, but does not propose a new feature. A process TIP is like an informative TIP but the provided guidelines are mandatory in a certain context \(as specified in the TIP itself\). Voting by the TCT as per the charter \(see [[0]](0.md)\) is required to make a project or process TIP official. # TIP Workflow The TIP editor, Donal K. Fellows <[email protected]> _pro tem_, is responsible for assigning numbers to each TIP and managing its status on behalf of authors. Everyone in the community can submit a TIP to the TIP editor. It should contain at least a proposed title and a rough, but fleshed out, draft of the TIP. It _must_ include a copyright statement that permits the normal business of the TIP process as described here. If the TIP editor approves, he will assign the TIP a number, label it as either project, process or informational, give it status _Draft_, and create and check-in the initial draft of the TIP. The TIP editor will not unreasonably deny a TIP. Reasons for denying TIP status include gross malformatting, inappropriate copyright, duplication of effort, being technically unsound, or not in keeping with the Tcl philosophy; the TCT and after that John Ousterhout <[email protected]> is the final arbitrator of the latter, as defined in the charter \([[0]](0.md)\). Discussion concerning a TIP should initially be kept out of the tclcore and tct mailing lists. Instead, comments should be sent to, and collected by, the TIP author, who has the responsibility to incorporate these comments into the document. _Note:_ It has been proposed to create a new mailing list for each TIP to handle its discussion. Rejection and finalization of the TIP closes the mailing list, but not the archive. Together with the CVS history a complete record of the development of a TIP will be available. The authors of the TIP are responsible for writing the TIP and marshaling community support for it. The structure of a TIP is described in detail in [[3]](3.md). A project TIP consists in principle of two parts, a design document and a reference implementation. The TIP will not normally be reviewed and accepted before a reference implementation is begun so that the amount of time between acceptance and a final implementation can be minimized. The implementation can be given in the form of code, patch, or URL to same, and _must_ be applied to the Tcl/Tk core before it can be considered _Final_; while small reference implementations may be placed inside the TIP itself, large reference implementations should be held externally and linked to by reference \(typically a URL\). Authors are encouraged to use the SourceForge Patch trackers for this purpose. Process and Informational TIPs do not need an implementation. TIP authors are responsible for collecting community feedback on a TIP before submitting it for review \(the creation of a TIP is a part of that review process.\) However, wherever possible, long open-ended discussions on public mailing lists should be avoided. A better strategy is to encourage public feedback directly to the TIP author, who collects and integrates the comments back into the TIP. Once the authors have completed a TIP, they must inform the Tcl Core Team that it is ready for review. TIPs are reviewed by the Tcl Core Team and \(for Project TIPs\) the maintainers for the relevant parts of the core, who may accept or reject a TIP or send it back to the author\(s\) for revision \(as detailed in [[0]](0.md).\) The acceptance or rejection of a TIP will cause its state to be changed accordingly to _Accepted_ or _Rejected_. Once a TIP requiring a reference implementation has been accepted, the reference implementation must be completed. When the reference implementation is complete and accepted by the TCT \(who can reject it if they feel the implementation would damage the rest of the core\) the status will be changed to _Final_. This is usually done by the TIP Editor, as advised by the responsible Tcl/Tk maintainer. A TIP can also be assigned status _Deferred_. The TIP author or the editor can assign the TIP this status when no progress is being made on the TIP. Once a TIP is deferred, the TIP editor can re-assign it to _Draft_ status. A TIP can also be _Withdrawn_ by the author. Perhaps after all is said and done, the author believes it was not a good idea. It is still important to have a record of this fact. It is expected that _Accepted_ TIPs will only be withdrawn very rarely, and _Final_ TIPs only under exceptional circumstances. TIP workflow is as follows: ![TIP Workflow](../assets/2workflow.gif) Some informative TIPs may also have a status of _Active_ if they are never meant to be completed. For example: [[1]](1.md). # What belongs in a successful TIP? Each TIP should have the following parts: 1. _Title_ - a short, descriptive title. 2. _Author_\(s\) - names and contact info \(email addresses\) for each author. 3. _Abstract_ - a short \(typically <200 word\) description of the technical issue being addressed. 4. _Copyright_/public domain - Each TIP must either be explicitly labelled in the public domain \(the preferred 'license'\) or the Open Publication License <http://www.opencontent.org/openpub/> . It is recommended that this be done by making the last section of the document be a copyright heading, with the body describing what copyright \(if any\) the document is released under. 5. _Specification_ - Project TIPs should have a technical specification that should describe the syntax and semantics of any new language feature. The specification should be detailed enough to allow \(competing\) interoperable implementations for any of the current Tcl platforms. 6. _Rationale_ - The rationale fleshes out the specification by describing what motivated the design and why particular design decisions were made. It should describe alternate designs that were considered and related work, _e.g._ how the feature is supported in other languages. > The rationale should provide evidence of consensus within the community and discuss important objections or concerns raised during discussion. 7. _Reference Implementation_ - The reference implementation must be completed before any TIP requiring such is given status _Final_, but it need not be completed before the TIP is accepted. It is better to finish the specification and rationale first and reach consensus on it before writing code. > The final implementation must include test code and documentation appropriate for either the Tcl language reference or the standard library reference. # TIP Style TIPs are written in plain ASCII text with an RFC822-like header and embedded sequences suitable for Wiki-like processing as indicated in [[3]](3.md). There are Tcl scripts that convert the TIP into HTML for viewing on the web. Scripts for producing other formats are available too, for example LaTeX and plain ASCII. # Sample Project TIP \(With thanks to William H. Duquette <[email protected]> for suggesting this.\) Note that the TIP Editor is responsible for allocating TIP numbers, so you can leave that unfilled. TIP: ??? Title: The TIP Title as Plain Text Version: $Revision: 1.38 $ Author: Author Name <[email protected]> State: Draft Type: Project Tcl-Version: 8.4 Vote: Pending Created: 31-Feb-1999 Post-History: ~ Abstract This is an example of how to write a simple project TIP. This is the abstract which should consist of a single paragraph of under 200 words. If you need more than this, you should stop and think about writing a real abstract, not a whole section! :^) ~ Some Sections Yada yada yada. Look at the sources to the various TIPs for tricks on how to do various things. ''Note that for complete legal safety, you must specify what copyright is used.'' We prefer public domain, as it allows others (notably the TIP editor(s)) to maintain the TIP as necessary without having to seek permission. I also prefer to make sure TIP and section titles are capitalized according to the usual rules of English. ~ Copyright This document has been placed in the public domain. A more complex example is [[7]](7.md) by Kevin Kenny <[email protected]> \(the source is at <http://www.cs.man.ac.uk/fellowsd-bin/TIP/7.tip\)> and which includes demonstrations of how to use advanced features like figures and verbatim text. His is a very high quality TIP though, and it has been though several revisions; don't feel too put off if your first attempt isn't quite as good... # Patches For preference, patches to Tcl should be stored separately on another website or submitted as a separate file. This is because \(quite rightly\) the news:comp.lang.tcl.announce moderator does not allow patches to be posted on that newsgroup. If you want a patch to be incorporated into the archive, please contact the TIP Editor. ---- # Comments > From Don Porter < [email protected] > : > 1. It is confusing that "project" TIPs defined here do not correspond to "projects" defined in [[0]](0.md). > 2. The TIP Workflow section should mention the web-based drafting service [[13]](13.md) as another way for members of the community to add their comments to a draft TIP. > 3. The TIP Workflow section calls for TCT acceptance of a project TIP implementation to move it from state Accepted to state Final. This conflicts with [[0]](0.md) which delegates that acceptance task to maintainers. > 4. It is not clear how the TIP workflow state diagram applies to non-project TIPs. Non-project TIPs do not have an implementation. Do they move straight from state Draft to state Final when they receive TCT approval? Or do they just stay in state Accepted forever with no need to move to state Final? > 5. It should be noted in the TIP Workflow section that according to [[0]](0.md) a project TIP cannot be approved \(and therefore should not be sponsored\) until the TIP names a committed implementor. > 6. The Patches section indicates that patches in the TIP are incompatible with posting to comp.lang.tcl.announce, so earlier sections of this TIP should not indicate that including patches in the TIP is an acceptable practice. > 7. Should process TIPs be reserved for those proposals that revise [[0]](0.md) and require 2/3 support of the entire TCT? From Mo DeJong: It seems like we have a documentation problem with respect to how a TIP becomes "un-rejected". The text says: > ... may accept or reject a TIP or send it back to the author\(s\) for revision" But the state transition diagram shows no way to go from _Rejected_ to _Draft_. What becomes of a TIP after it is put up for a vote? If it is rejected, should the author create a new TIP number or can they rewrite the original TIP? ---- _Larry W. Virden writes:_ I would really find it useful if upon submission of a TIP, a web page, perhaps on the Tcl'ers Wiki or elsewhere, would be referenced in the TIP itself. This web page would contain a summary of the discussion to date, perhaps containing urls to relevant postings within the tct archives, etc. This page could be used by those looking at the archive to quickly determine the state of the discussion, as well as the reasons for the final disposition of the TIP. _Donal Fellows responds:_ Feel free to establish such things. But I've definitely not got time to maintain them, and especially haven't got time to go back through the archives to make the resource complete for those TIPs that have already been voted upon. ---- # Copyright This document has been placed in the public domain. |
Name change from tip/20.tip to tip/20.md.
|
| < | < | | | | | | | > | | | | | | | | | | | > | 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 | # TIP 20: Add C Locale-Exact CType Functions Author: Jeffrey Hobbs <[email protected]> State: Deferred Type: Project Tcl-Version: 8.5 Vote: Pending Created: 08-Jan-2001 Post-History: ----- # Abstract This TIP adds functions to Tcl that are a subset of the standard ctype functions \(isspace, isalpha, ...\) that are ensured to operate only in the C locale \(char < 0x80\). # Rationale Tcl used to force the C locale everywhere in order to have parsing work as expected throughout Tcl, but that prevented certain i18n features from working correctly \(like native character input\). In enabling the i18n features, some bugs \(like <http://sf.net/bugs/?func=detailbug&bug_id=127512&group_id=10894> \) were exposed that required the C locale to be enabled to function properly. Since we don't want to force that requirement, creating ctype functions that work as if they were always in the C locale is the best solution. # Reference Implementation Add a file _generic/tclC.c_ \(to parallel _generic/tclUtf.c_\) that contains functions following the convention C\_isspace, C\_isalpha, ... These functions would use character or bit maps to ensure greatest speed and efficiency of the functions. Not all use of the ctype functions need be replaced. Those that walk over a string, especially backwards, are the ones that need replacement. # Copyright This document is in the public domain. |
Name change from tip/200.tip to tip/200.md.
|
| < | < | | | | | | | | | > | | | | | | | < > | | | | < > | | | | | | | | | | | | | < | > | | | < | > | | > | 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 | # TIP 200: Listing the Values in an Array Author: Donal K. Fellows <[email protected]> Author: Dossy Shiobara <[email protected]> State: Rejected Type: Project Vote: Done Created: 20-May-2004 Post-History: Keywords: Tcl Tcl-Version: 8.5 ----- # Abstract This TIP proposes adding another subcommand to the **array** command to list the values in an array. # Rationale Currently, the easiest ways of building a list of all values within an array involve either iterating over the names of the array elements and then reading the value at each step, or iterating over the result of **array get** and dropping the _name_ part of each pair, as can be seen from these code examples: set list {} foreach name [array names SomeArray] { lappend list $SomeArray($name) } set list {} foreach {name value} [array get SomeArray] { lappend list $value } Neither of these is especially efficient, since the first does a very large number of array reads, and the second builds a very large intermediate list \(particularly if you subsequently want to filter the values to select a subset of them.\) It would be better if the functionality was added directly to the Tcl core, especially as the conceptual overhead would be very low as there are already subcommands of **array** for returning both the names of the array and the name/value pairs. # Proposed Change I propose to add a new subcommand to **array** called **values** with the following syntax: > **array values** _arrayName_ ?_globPattern_? This returns a list of values that are contained in the array in the "natural order" of the values within the array. The optional _globPattern_ argument allows for returning only some of the values in the array \(those values for keys that match the pattern according to the rules of **string match**\). The pattern will not change the ordering of the list; it only filters the result. The order of the values returned shall be such that the following two **foreach** iterations shall behave identically \(modulo traces on the array variable\): foreach {name value} [array get AnyArray $pattern] { AnyScript } foreach name [array names AnyArray $pattern] \ value [array values AnyArray $pattern] { AnyScript } Note that this implies that the resulting list from **array values** may well contain duplicates, and that none of the values actually returned will necessarily match the supplied pattern. # Copyright This document has been placed in the public domain. |
Name change from tip/201.tip to tip/201.md.
|
| < | < | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 201: Add 'in' Operator to [expr] Author: Jeff Hobbs <[email protected]> State: Final Type: Project Vote: Done Created: 21-May-2004 Post-History: Keywords: Tk,list membership,sets Tcl-Version: 8.5 ----- # Abstract This TIP proposes new **expr** operators "**in**" and "**ni**" that simplifies the standard "does this item exist in list" **lsearch** case in expressions, with "**ni**" being "not in". # Rationale The addition of **in** and **ni** operators is syntactic sugar for the verbose **lsearch** operation that checks for a single items existence \(or non-existence\) in a list. It serves to simplify the reading and writing of code that requires this comparatively-common operation. The operators will do **lsearch -exact** searching as well, which would correct an inadvertant bug that many users introduce into their code when they write: if {[lsearch $list $item] != -1} { ... } as **lsearch** does **-glob** matching by default. I have found this error repeated often in user code. Note that [[133]](133.md) uses an **in** operator as a motivating case, but is actually proposing a much more general alteration. # Specification A new infix **expr** operators **in** and **ni** will be added, making the following pairs of commands equivalent \(assuming nobody has redefined **lsearch** of course\): * Searching for an arbitrary item in an arbitrary list. if {[lsearch -exact $list $item] != -1} { ... } if {$item in $list} { ... } * Checking for the absence of an arbitrary item from an arbitrary list. if {[lsearch -exact $list $item] == -1} { ... } if {$item ni $list} { ... } # Comments There was a proposal to add a separate operator "**!in**" to do negated membership testing, but that significantly complicates the expression parser and is likely to be harder to teach to newcomers to Tcl, since it looks like the application of an operator to another operator. **notin** and **ni** were also suggested, and **ni** was accepted as a reasonable pair for "not in", similar to **ne** being "not equal". There was some concern about **ni** in that TeX has a different interpretation, but that is unlikely to confuse the majority of Tcl users. # Reference Implementation _[To Follow]_ # Copyright This document has been placed in the public domain. |
Name change from tip/202.tip to tip/202.md.
|
| < | < | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 202: Add 2>@1 Special Case to [open] and [exec] Author: Jeff Hobbs <[email protected]> State: Final Type: Project Tcl-Version: 8.5 Vote: Done Created: 19-May-2004 Post-History: Keywords: Tcl, redirection ----- # Abstract This TIP proposes adding a new redirection case '2>@1' that redirects the error channel to the output channel in **open** and **exec**. This would only be valid at the end of a pipeline. # Rationale Tcl is currently limited on how _stderr_ can be managed from a command opened with **open \|** or **exec**. This TIP adds the ability to simply combine the _stderr_ stream with the _stdout_ stream by adding a new output redirection case, **2>@1** \(i.e. as in Bourne shell syntax\), that is only ever valid as the last redirection item in a pipeline. This will enable simple capturing of _stderr_ as well as _stdout_ across platforms. The behavior is similar to **2>@stdout**, but that does not work across platforms. The difference is that directs to a real _stdout_ file channel \(which is not available in Windows wish for example\), whereas **2>@1** would redirect to the output result for **exec**/**open**. The intention is to handle the common case of wanting to capture _stderr_ as well as _stdout_ output from a single command. This operator is only valid as the last redirection operator. To redirect _stderr_ of previous commands along with their _stdout_, use the preexisting **\|&** pipe operator. This is backwards compatible as **2>@1** currently raises an error that "1" is not a valid file id \(Tcl does not create such file ids\). ## Examples set fid [open "|$cmd 2>@1"] set result [exec $cmd 2>@1] # Reference Implementation See SF Tcl Patch 957132 <http://sf.net/tracker/?func=detail&aid=957132&group_id=10894&atid=310894> for details. # Copyright This document has been placed in the public domain. |
Name change from tip/203.tip to tip/203.md.
|
| < | < | | | | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 203: Create tclConfig.sh-Equivalent in Tcl Author: Colin McCormack <[email protected]> Author: Don Porter <[email protected]> Author: Colin McCormack <[email protected]> State: Withdrawn Type: Project Vote: Pending Created: 17-Jun-2004 Post-History: Discussions-To: http://mini.net/tcl/tclConfig.sh Keywords: configuration,installation Tcl-Version: 8.5 ----- # Abstract This proposal requires the registration of information about the built process, currently stored in tclConfig.sh, by means of the Tcl\_RegisterConfig mechanism set out in [Tip 59]. # Rationale Packages such as Critcl<http://www.equi4.com/critcl.html> , and indeed anything written in pure tcl which tries to build extensions under Tcl need more introspection to discover the ground rules of construction in the installation in which they find themselves. In order to facilitate such future build tools, the build information should be made available to Tcl scripts. # Specification Every variable defined in the unix tclConfig.sh should be registered using **Tcl\_RegisterConfig**, with the following exceptions: * TCL\_VERSION and similar redundant version, patch level information. * TCL\_THREADS - redundant. * TCL\_BUILD\_\* - nothing specifying the build directory. Because Windows and other platforms don't have a tclConfig.sh, the following fields are desirable for hand construction: ---- **Compilation:** * TCL\_CC \# C compiler to use for compilation. * TCL\_DEFS \# -D flags for use with the C compiler. * TCL\_INCLUDE\_SPEC \# String to pass to the compiler so that an extension can find installed Tcl headers. * TCL\_LIB\_FILE \# The name of the Tcl library * TCL\_LIBS \# Additional libraries to use when linking Tcl. * TCL\_SHLIB\_CFLAGS \# Flags to pass to cc when compiling the components of a shared library: * TCL\_CFLAGS\_WARNING \# Flags to pass to cc to get warning messages * TCL\_EXTRA\_CFLAGS \# Extra flags to pass to cc: ---- **Linking:** * TCL\_SHLIB\_LD \# Base command to use for combining object files into a shared library: * TCL\_SHLIB\_LD\_LIBS \# dependent libraries should be included when linking shared libraries * TCL\_SH LIB\_SUFFIX \# Suffix to use for the name of a shared library. * TCL\_LD\_FLAGS \# Flags to pass to the compiler when linking object files into an executable tclsh or tcltest binary. * TCL\_COMPAT\_OBJS \# Additional object files linked with Tcl to provide compatibility with standard facilities from ANSI C or POSIX. * TCL\_LIB\_FLAG \# -l flag to pass to the linker to pick up the Tcl library * TCL\_LIB\_SPEC \# String to pass to linker to pick up the Tcl library from its installed directory. ---- **Stub Support:** * TCL\_SUPPORTS\_STUBS \# Tcl supports stub. * TCL\_STUB\_LIB\_FILE \# The name of the Tcl stub library \(.a\): * TCL\_STUB\_LIB\_FLAG \# -l flag to pass to the linker to pick up the Tcl stub library * TCL\_STUB\_LIB\_SPEC \# String to pass to linker to pick up the Tcl stub library from its installed directory. * TCL\_STUB\_LIB\_PATH \# Path to the Tcl stub library in the install directory. ---- # Comments How about converting this proposal into a proposal listing the values found in _tclConfig.sh_ and proposing that Tcl should pass those values into **Tcl\_RegisterConfig** during initialization? That would make all the values available to scripts via the **::tcl::pkgconfig** command. -- Good idea. Done. Several of the assigned values in tclConfig.sh contain references to other variables - should these be reproduced verbatim, or evaluated prior to registration? I'm leaning toward verbatim storage: let the people who need the data construct an evaluation which serves their purposes because \(a\) the form is easy enough to evaluate, as in the parser I threw together <http://mini.net/tcl/tclConfig.sh> , \(b\) there might be information in the verbatim form which needs to be preserved. Comments welcome. # Withdrawal Joe English points out that those parts potentially useful to a pure-tcl builder are not necessarily applicable, since the build and installation machines may/will differ substantially, and that those parts universally applicable are available via some combination of info and ::tcl::pkgconfig. Given this insight, I withdraw this TIP. # Copyright This document has been placed in the public domain. |
Name change from tip/204.tip to tip/204.md.
|
| < | < | | | | | | | > | | | | | | | | | | | | | | | | > | 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 | # TIP 204: Virtual Events for Keyboard Traversal Author: Joe English <[email protected]> State: Final Type: Project Tcl-Version: 8.5 Vote: Done Created: 21-Jun-2004 Post-History: ----- # Abstract Proposes using two new virtual events, **<<TraverseIn>>** and **<<TraverseOut>>**, to notify widgets of keyboard navigation events. # Rationale Certain widgets need to perform some action when they receive and/or lose keyboard focus because of keyboard traversal. For example, tabbing into an Entry or Spinbox widget selects the widget contents. This cannot be done with a <FocusIn> binding, since widgets may receive <FocusIn> events for reasons other than keyboard traversal. Tk currently implements this feature with special-case logic that checks the target window's widget class in the _tk::TabToWindow_ procedure. The drawback to this approach is that it only works for the built-in widgets; third party widget sets like BWidget<http://tcllib.sf.net/> , IWidgets<http://sf.net/projects/incrtcl/> , and Tile<http://tktable.sf.net/tile/> must implement their own workarounds. # Proposal Change the standard Tk bindings for <Key-Tab> and <Shift-Key-Tab> to do the following: * Send a **<<TraverseOut>>** virtual event to the current focus window, if any; * Set the focus to the new window; * Send a **<<TraverseIn>>** virtual event to the new window. Additionally, move the current code to handle traversal to Entry and Spinbox widgets from _tk::TabToWindow_ to class bindings. # Implementation See Tk Patch \#976928<http://sourceforge.net/support/tracker.php?aid=976928> . The BWidget package has used an identical scheme since version 1.7; see Tcllib bug \#720032<http://sourceforge.net/support/tracker.php?aid=720032> for details. # Copyright This document has been placed in the public domain. |
Name change from tip/205.tip to tip/205.md.
|
| < | < | | | | | | | > | | | | | | | | | | | | | | | | | | > | 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 | # TIP 205: Use pkgconfig Database to Register Xft Support Author: Joe English <[email protected]> State: Final Type: Project Vote: Done Created: 23-Jun-2004 Post-History: Tcl-Version: 8.5 ----- # Abstract This TIP proposes to use Tcl's package configuration database \(see [[59]](59.md)\) to register whether Tk was compiled with support for Xft. # Rationale As of version 8.5, Tk has optional support for Xft \(the modern replacement for server-side fonts in X11\). However, at present application code has no way to determine whether or not Xft support was enabled when Tk was built. The package configuration database facility introduced in [[59]](59.md) seems like an ideal place to record this information. # Proposal If Tk was configured with _--enable-xft_, the command tk::pkgconfig get fontsystem shall return the value **xft**. # Notes The change as currently proposed is the minimum necessary to satisfy the requirement listed in the Rationale. In particular: nothing else in Tk currently calls _Tcl\_RegisterConfig\(\)_, so if Xft support is not enabled the **tk::pkgconfig** command will remain undefined. This TIP \(or something like it\) is a prerequisite for a script-level implementation of [[145]](145.md), which will need to distinguish whether or not Xft is in use. # Implementation See Tk Patch \#976520<http://sourceforge.net/support/tracker.php?aid=976520> # Copyright This document has been placed in the public domain. |
Name change from tip/206.tip to tip/206.md.
|
| < | < | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 206: Add an [ftruncate] Command Author: Joe Mistachkin <[email protected]> State: Rejected Type: Project Vote: Done Created: 25-Jun-2004 Post-History: Tcl-Version: 8.5 Obsoleted-By: 208 ----- # Abstract This TIP proposes a new command **ftruncate** for truncating open files. # Note This TIP has been effectively rolled into [[208]](208.md). # Rationale In Tcl, there is currently no way to truncate a file while it is open even though all modern operating systems support such an operation. The current workaround is to close the file and reopen it. However, in cases where the file must be held open \(e.g. on Unix where the file has already been deleted and is just being used as scratch space\) this workaround cannot be used. # Specification > **ftruncate** _channelId_ ?_length_? The channel specified by _channelId_ must refer to a file that was opened for writing. The _length_ argument must be greater than or equal to zero and can be bigger than the current size of the file. If the _length_ argument is omitted, the file will be truncated at the current access position. This command will return any errors received from the operating system. ## Example Usage # Open the file for reading and writing... set file [open "test.txt" {RDWR}] # Write some data to the file... puts $file "test data" # Some time later... # ... ... ... ftruncate $file # ... ... ... # We are done, close the file... close $file # Proposed C API Changes A new function named **Tcl\_TruncateChannel** would be added to the Tcl C API \(taking two arguments, the channel to truncate and the length \(as a wide integer to facilitate use with large files\) to truncate it to in bytes\). The channel API would be modified to add the new functionality for standard disk file channels and to allow extension authors to implement it for their custom channel types through specifying in their _Tcl\_ChannelType_ structure a value for the new field _truncateProc_ \(of type pointer to _Tcl\_DriverTruncateProc_, which will be a function with the obvious type signature\). Finally, the maximum TCL\_CHANNEL\_VERSION would be increased to TCL\_CHANNEL\_VERSION\_4 to accommodate this new field. # Reference Implementation A reference implementation does _not_ yet exist. # Copyright This document has been placed in the public domain. |
Name change from tip/207.tip to tip/207.md.
|
| < | < | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 207: Add a -namespace Option to [interp invokehidden] Author: Joe Mistachkin <[email protected]> Author: Don Porter <[email protected]> State: Final Type: Project Vote: Done Created: 29-Jun-2004 Post-History: Tcl-Version: 8.5 ----- # Abstract This TIP proposes a _-namespace_ option for the **interp invokehidden** subcommand to allow hidden commands to be invoked in the specified namespace context in the slave interpreter. # Rationale Safe interpreters and namespaces have been useful and important features of Tcl since version 8.0. However, it can sometimes be difficult to use them together effectively. For example, while you can invoke a hidden command in a safe interpreter with **interp invokehidden**, such as **source**, you cannot specify the target namespace context where the command should be invoked. Using the **interp eval** subcommand is not an option because that, by design, does not allow hidden commands to be invoked. In addition, since the **interp invokehidden** subcommand expects a command name, **namespace eval** and similar constructs that would typically be used to change the target namespace context cannot be used. # Specification > **interp invokehidden** _path_ ?**-namespace** _namespace_? ?**-global**? ?**--**? _hiddenCmdName_ ?_arg ..._? The **interp invokehidden** subcommand would continue to function as the current documentation dictates with the following notable exceptions: * The **-namespace** specifies the target namespace context in the slave interpreter where the command should be invoked starting from the global namespace in the slave interpreter. * The target namespace context specified by the **-namespace** option is created in the slave interpreter if it does not already exist. * If both the **-global** and **-namespace** options are present, the **-namespace** option is ignored. A **--** option \(with the standard meaning\) will be added as well. The slave-interpreter command version of **invokehidden** will be updated in an equivalent way. ## Example Usage The following example scripts illustrates how this feature might be used. ################################################ # file inside.tcl ################################################ set x "this is a test from inside [namespace current]." ################################################ # file invoke.tcl ################################################ set i [interp create -safe] set file [file join [file dirname [info script]] inside.tcl] interp invokehidden $i -namespace ::test::foo::bar source $file set result [interp eval $i [list set ::test::foo::bar::x]] # should be: "this is a test from inside ::test::foo::bar." puts stdout $result # Proposed Internal C API Changes To be determined. # Reference Implementation A reference implementation of this TIP is availble <http://sf.net/tracker/?func=detail&aid=981841&group_id=10894&atid=310894> . # Comments _DGP_: Note that the **interp** command \(including the **interp invokehidden** subcommand\) was added for Tcl 7.5. The **namespace** command arrived later in Tcl 8.0. This proposal observes and proposes to correct that the **interp invokehidden** command was not updated to account for the arrival of namespaces. Clearly the _-global_ option indicates that control over evaluation context is something the caller needs. This command simply failed to evolve in a timely manner. This proposal is an overdue correction. Looking ahead, I'd be happy if the _-global_ option was dropped from the documentation, so that only the new _-namespace_ option is favored, and so that the recommended way one forces evaluation in the global namespace is with _-namespace ::_. The _-global_ option would still work through the remaining Tcl 8 releases, but no longer be recommended for new code. # Copyright This document has been placed in the public domain. |
Name change from tip/208.tip to tip/208.md.
|
| < | < | | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 208: Add a 'chan' Command Author: Jeff Hobbs <[email protected]> State: Final Type: Project Vote: Done Created: 02-Jul-2004 Post-History: Keywords: Tcl Tcl-Version: 8.5 Obsoletes: 206 ----- # Abstract This TIP proposes adding a **chan** command that would serve as a top-level command container for all the related channel commands that have proliferated over time, as well as future new channel-based commands. # Rationale Tcl's channel system has evolved over time from a thin layer on top of the OS into a very complex, multi-platform system. There are numerous top-level commands for channels already, with more being proposed for Tcl 8.5. This command would centralize them, making it easier for new users to see all the related channel commands, much as **string** or **file** operate today. The name **chan** was chosen over "channel" because it is a clearly recognizable abbreviation, much like **eval** vs. "evaluate" and **interp** vs "interpreter". # Specification A new command **chan** will be added with the following syntax: chan blocked ; # fblocked chan close ; # close chan configure ; # fconfigure chan copy ; # fcopy chan eof ; # eof chan event ; # fileevent chan flush ; # flush chan gets ; # gets chan names ; # file channels chan puts ; # puts chan read ; # read chan seek ; # seek chan tell ; # tell chan truncate ; # ftruncate (if TIP#206 had been accepted) Each represents the existing command that is commented. The arguments to each would remain what the current command takes. Note that **open** is not included above, as it is a channel creation function, just like **socket**. ## Specification of the 'truncate' Subcommand [See [[206]](206.md) for Rationale] > **chan truncate** _channelId_ ?_length_? The channel specified by _channelId_ must refer to a file that was opened for writing. The _length_ argument must be greater than or equal to zero and can be bigger than the current size of the file. If the _length_ argument is omitted, the file will be truncated at the current access position. The result of this command will normally be the empty string; any errors from the filesystem when truncating will generate error results in the normal fashion. ## Deprecation of Existing Commands In addition, I would recommend only the following commands be marked deprecated so as to help systematize their names better: fblocked fconfigure fcopy fileevent file channels # Related C API Changes A new function named **Tcl\_TruncateChannel** would be added to the Tcl C API \(taking two arguments, the channel to truncate and the length \(as a wide integer to facilitate use with large files\) to truncate it to in bytes\). > int **Tcl\_TruncateChannel**\(Tcl\_Channel _chan_, Tcl\_WideInt _length_\) The channel API would be modified to add the new functionality for standard disk file channels and to allow extension authors to implement it for their custom channel types through specifying in their _Tcl\_ChannelType_ structure a value for the new field _truncateProc_ \(of type pointer to _Tcl\_DriverTruncateProc_, which will be a function with the obvious type signature\). Finally, the maximum TCL\_CHANNEL\_VERSION would be increased to TCL\_CHANNEL\_VERSION\_4 to accommodate this new field. # Reference Implementation The implementation of the Tcl-level TIP is really a simple command that makes use of the existing command implementations. It could be a namespace ensemble or a C-based command. The **chan truncate** part will require C code. # Copyright This document has been placed in the public domain. |
Name change from tip/209.tip to tip/209.md.
|
| < | < | | | | | | | | > | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 209: Add [clock milliseconds], and [clock microseconds] Author: Reinhard Max <[email protected]> State: Final Type: Project Vote: Done Created: 12-Jul-2004 Post-History: Keywords: clock, milliseconds, microseconds Tcl-Version: 8.5 ----- # Abstract This TIP proposes to replace **clock clicks -milliseconds** by **clock milliseconds** and **clock clicks -microseconds** by **clock microseconds**. # Proposed change 1. Rename the **clock clicks -microseconds** command as defined by [[124]](124.md) to **clock microseconds**. 2. Deprecate **clock clicks -milliseconds**, and make it's functionality as defined by [[124]](124.md) available as **clock milliseconds**. # Rationale In the author's understanding, the whole purpose of the **clock clicks** name was to indicate that the returned value is neither absolute nor guaranteed to have the same unit on different platforms. With the changes of [[124]](124.md) in place both cases are not true anymore. Therefore the commands to return absolute timestamps with millisecond and microsecond resolution should be on the same level as **clock seconds** rather than being switches to **clock clicks**. The **-microseconds** option can be removed from **clock clicks** immediately, because it never has been part of an official Tcl release while **-milliseconds** has to be kept at least until the next major release for backwards compatibility. # Reference Implementation A reference implementation has been added to the Tcl patch tracker at SourceForge, item \#991742 . # Copyright This document has been placed in the public domain. |
Name change from tip/21.tip to tip/21.md.
|
| < | < | | | | | | | > | | | | | | | | | | | | | | > | 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 | # TIP 21: Asymmetric Padding in the Pack and Grid Geometry Managers Author: D. Richard Hipp <[email protected]> State: Final Type: Project Vote: Done Created: 14-Jan-2001 Post-History: Tcl-Version: 8.4 ----- # Abstract Proposes modifying the _pack_ and _grid_ geometry managers to support asymmetric padding. # Rationale The _pack_ and _grid_ geometry managers allow for adding extra space to the left and right of a widget using the -padx option, and above and below the widget using -pady. But there is currently no way to add different amounts of space on opposite sides of the widget. When a layout requires differing amounts of space on opposite sides of the same widget, the usual solution is to introduce extra _frame_ widgets to act as spacers. But that both complicates the code unnecessarily and obscures the intent of the programmer. # Proposed Enhancement This TIP proposes to modify the -padx and -pady of both the _pack_ and _grid_ geometry managers as follows: If the argument to -padx or -pady is a screen distance, that distance is added to both sides of the widget. \(This is the current behavior.\) If the argument is a list of two screen distances, then the first screen distance is the extra space to add to the left or top and the second screen distance is the extra space to add to the right or bottom. The changes to -padx and -pady occur in _pack_ only if the pack geometry manager is used according to the new syntax. The older deprecated syntax \(that dates from Tk3.3\) will not support asymmetric padding. # Copyright This document has been placed in the public domain. # Patch Patches to implement asymmetric padding in the pack and grid geometry managers, as described above, are available at <http://www.hwaci.com/sw/asym\_pad\_patch\_2.txt> |
Name change from tip/210.tip to tip/210.md.
|
| < | < | | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 210: Add 'tempfile' Subcommand to 'file' Author: Bob Techentin <[email protected]> Author: Donal K. Fellows <[email protected]> State: Final Type: Project Vote: Done Created: 19-Jul-2004 Post-History: Keywords: Tcl,filename Tcl-Version: 8.6 ----- # Abstract Programmers often need to create temporary files. This TIP proposes adding the new subcommand **tempfile** to the **file** command, simplifying programmer effort in creating a unique temporary file name. # Rationale Creating temporary files is a primitive and common enough operation that the ANSI C standard defines several subroutines to assist programmers. The _tmpnam\(\)_ function generates a string that is a valid file name that is not the name of an existing file. The _tmpfile\(\)_ function returns a valid file pointer to a temporary file that is removed automatically when it is closed or at program termination. Both functions are commonly used by programmers, without worrying about the optimal location for temporary files or schemes required to create unique file names. Tcl has not supported temporary files, so programmers have had to write code to generate unique file names and choose locations like _/tmp_ or _C:\\temp_. The _fileutil_ module of tcllib provides a relatively sophisticated implementation of _tempfile_, but extension writers have not been able to rely on this code. Modules in Iwidgets, the Tcl plugin, tcllib, and TclX all appear to have this sort of code, and not all are correct. This TIP proposes to extend the **file** command with one subcommand to generate temporary files and file names. By extending the core command, application programmers and extension writers will be able to depend on this functionality for their code, without resorting to copying or depending on tcllib. # Specification This TIP proposes an extension to the **file** command, implementing the functionality of the POSIX standard mkstemp\(\) function. The new subcommand will be called **tempfile**. It will return an open file channel, and \(optionally\) the name of the temporary file. # Synopsis > **file tempfile** ?_namevar_? ?_template_? Opens a unique temporary file and returns an open file channel. If _namevar_ is specified, then the command will set the variable to the name of the temporary file. If the _template_ string is specified, it will be decomposed into \(up to\) three parts: the path, the root, and the extension. Any part may be absent. If the path or root are absent, system-dependent defaults will be used. If the extension is absent, no extension will be used. The temporary name will then be formed from the path, the root, some unique string, and the extension \(if defined\). The returned channel will have been opened in read-write mode \(but not append mode\) using the defaults for EOL translation, encoding, etc. # Reference Implementation Available as Tcl Patch \#999162 on SourceForge <https://sourceforge.net/support/tracker.php?aid=999162> . _\(That patch is for an old version of the TIP.\)_ # Copyright This document has been placed in the public domain. |
Name change from tip/211.tip to tip/211.md.
|
| < | < | | | | | | | | | | | > | | | | | | | | | | < > | | < > | | | | < < > > | | | | | | | | < < > > | | | | | | | | | | | | | | | | < | | > | | | | | | | | | | | | | | | | | > | 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 | # TIP 211: Add Full Stack Trace Capability Author: Robert Seeger <[email protected]> Author: Robert Seeger <[email protected]> Author: Don Porter <[email protected]> State: Withdrawn Type: Project Vote: Pending Created: 10-Aug-2004 Post-History: Keywords: Tcl Tcl-Version: 8.5 Obsoleted-By: 280 ----- # Abstract This TIP proposes adding a new subcommand to the **info** command to get a list of all the frames on the current stack, rather than the limited list returned by **info level**. # Rationale Currently, there is no way to get a list of all the frames in the current stack managed by **Tcl\_PushCallFrame\(\)** and **Tcl\_PopCallFrame\(\)**. The **info level** command does not contain frames that are callers of **uplevel**, reporting only the frames that are accessible via another **uplevel** command. There are times when the lack of information can have a negative impact on code design. The difference in information can be seen with the following code snippets: % proc bob {args} { joe {expand}$args } % proc joe {args} { uplevel 1 dave {expand}$args } % proc dave {args} { puts "Level: [info level]" for {set i [info level]} { $i > 0 } {incr i -1 } { puts "${i}: [info level $i]" } } % bob x y z Level: 2 2: dave x y z 1: bob x y z % proc dave {args} { puts "Level: [info frame]" for {set i [info frame]} { $i > 0 } {incr i -1 } { puts "${i}: [info frame $i]" } } % bob Level: 3 3: dave x y z 2: joe x y z 1: bob x y z There are 3 reasons I see for bringing forth this TIP: 1. It's an introspection ability that is currently lacking, with no good reason for that lack. 2. The more information that is available to the programmer, the easier it is to accomplish a goal in a straightforward, easily maintainable way. 3. I have code in which the impact of not having this information available is visible. ## Use Cases There are two cases I have run into where the ability to query all frames on the stack would have been particularly useful. 1. **TclTest** > The first case is with Tcltest, where the complete lack of ability to gain access to that information means it is impossible to gain information about a test without modifying the Tcltest code itself. Being able to find out the name of the current test would be very handy, especially in naming test procs and logging information. Currently, there is no way to find out the name of the currently executing test, due to the fact that the code for the test is **uplevel**ed and, hence, not visible via **info level**. 2. **TestStubs Package** > The TestStubs package provides the ability to temporarily redefine commands, in particular for stubbing out or replacing functionality in a test case. There is a command in the package called **chain**, which is used within the code replacing a command \(or part of a command\) to call the original definition of the command. For example, one could do: stubs::stub ensemble array names { return [lsort [uplevel 1 chain names $args]] } > However, since the **chain** command is \(and should be\) limited to only running from within a stub definition, it needs to call **info level** to find out if its caller is one of the stubbed commands, and what the name of that command is. With **info level**, it would not have access to the level that is running inside the stubbed procedure. Hence, either it cannot check this constraint, or stubs cannot be allowed to use **uplevel** when calling it \(which means things like the above either cannot work, or need to be rewritten in a considerably less clear manner\). # Proposed Change I propose to add a new subcommand to the info command with the following syntax: > **info frame** ?_level_? The new functionality will provide access to all frames on the stack rather than the current limited subset. The information to do so already exists within the Interp object that all commands are passed, and the code needed to expose it differs in only a few aspects from that of **info level**. This TIP does _not_ propose to alter **uplevel** or **upvar** so that they can see these hidden levels. ## Child Interps The current implementation of _info level_ only returns levels up to the top of the stack for the current interpreter. Such an approach puts limitations on what information can be retrieved, but allows for a certain level of _"security"_ when running code in child interps, especially safe interps. Given the security considerations of safe interps, and consistancy with regards to what information is returned across multiple circumstances, the stack trace returned will only return information up to the top level of the current interp, the same limit _info level_ is bound by. # Implementation An implementation patch is available on SourceForge <http://sourceforge.net/tracker/?func=detail&aid=1503647&group_id=10894&atid=310894> . # Copyright This document has been placed in the public domain. Please note that any correspondence to the author concerning this TIP is considered in the public domain unless otherwise specifically requested by the individual\(s\) authoring said correspondence. This is to allow information about the TIP to be placed in a public forum for discussion. |
Name change from tip/212.tip to tip/212.md.
|
| < | | | | | | < | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | < | > | | | < < > > | | | < | > | | | < < > > | | | < | > | | | > | 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 | # TIP 212: Temporarily Opening out a Dictionary State: Final Type: Project Tcl-Version: 8.5 Vote: Done Post-History: Author: Donal K. Fellows <[email protected]> Created: 11-Aug-2004 Keywords: tcl, dict, update, script ----- # Abstract This TIP proposes a new subcommand of **dict** that associates variables with dictionary entries while a Tcl script \(the "body" of the command\) runs. # Rationale The standard set of operations provided by the **dict** command \(see [[111]](111.md) and [[163]](163.md)\) give a fairly rich set of operations, but there are always further things that script authors want to do. Instead of ever-expanding numbers of subcommands offering tiny variants on existing operations, this TIP provides a generalized mechanism for associating variables and dictionary entries for the duration of a script. This makes writing arbitrary complex manipulations of dictionaries much simpler. # Proposed Change This TIP proposes two new subcommands to **dict**, **update** and **with**, with the following syntaxes and semantics. ## The 'dict update' Subcommand > **dict update** _dictVarName dictKey varName_ ?_dictKey varName_ ...? _bodyScript_ In prose, the first argument is the name of a variable containing a dictionary that will be updated, the last argument is a script to be executed with the variables set up and whose effects are expected to be to update the associated variables, and the other arguments between those two \(of which there must be an even number, with a minimum of two\) are a list of dictionary keys and the names of variables with which to associate those keys. The semantics of the command are this: 1. For each dictionary key \(_dictKey_\), the value from the dictionary contained in the variable named by _dictVarName_ which that key maps to will be written to the variable associated with that key \(_varName_\). If the key is not present in the dictionary, the variable will be unset. 2. The script \(_bodyScript_\) is executed. 3. The dictionary is read out of _dictVarName_ again and, for each _dictKey_, the _varName_ variable is consulted and the contained value placed in the dictionary \(if _varName_ is unset, any existing mapping for _dictKey_ will be removed.\) Finally, the resulting dictionary value is written back to _dictVarName_. > If the _dictVarName_ variable was unset \(without being set to a new value\) or otherwise rendered unreadable during the execution of _bodyScript_, the updating of the keys and writing back of the resulting dictionary to _dictVarName_ is skipped. Note that it is only an unreadable _dictVarName_ that is treated this way; it is an error for the variable to contain a value that is not a valid dictionary. Note that _dictVarName_ is read twice \(each time, the value read must be a valid dictionary or the variable must be unset, which is interpreted as an empty dictionary\) and \(assuming the second read succeeds and returns a valid dictionary value\) written once, and that _no_ traces are set up; _dictVarName_ is completely independent of the _varName_s during the execution of _bodyScript_. Also note that step 3 is carried out even if _bodyScript_ completes with a result code other than TCL\_OK, and that the result code of the overall command will be the result code of the script unless TCL\_ERROR was the result of the write-back stage, which might happen if the variable _dictVarName_ is updated \(during the execution of _bodyScript_\) to contain a non-dictionary value, or if the variable _dictVarName_ is either unset or cannot be written to \(which can happen if a write trace throws an error\); note that this mandates that any errors from the _bodyScript_ are lost if the write-back phase also throws an error. If the result code is TCL\_OK, the result string/object will be whatever the result string/object of _bodyScript_ was. ## The 'dict with' Subcommand > **dict with** _dictVarName_ ?_key ..._? _bodyScript_ This is a shorthand version of **dict update** \(named after the Pascal _with_ keyword\) which maps _all_ of the keys in the dictionary in the variable _dictVarName_ to variables during the evaluation of _bodyScript_. Note that it builds a list of all the keys in the dictionary before _bodyScript_ runs and only those variables which are created are mapped back at the end; if extra keys are defined in the dictionary in the variable during the execution of _bodyScript_, they will be left alone when _bodyScript_ finishes. The variables will be written to and read from in the natural order of the keys of the dictionary in the variable _dictVarName_ when the **dict with** command starts. When a _key_ \(or several _key_s\) is provided, it describes a path into a nested set of dictionaries \(much like with **dict set**\) where the selected leaf indicates a dictionary that is to be opened out. When writing back, non-existence of any key on the path is treated the same as if _dictVarName_ itself didn't exist. # Examples A somewhat-less-efficient version of **dict set**: dict update someVar $key local { set local $value } Sorting a list inside a nested dictionary: dict update someVar OuterKey temp { dict update temp InnerKey temp2 { set temp2 [lsort $temp2] } } "Renaming" a key: dict update someVar oldKey foo newKey bar { set bar $foo unset foo } Opening out a nested dictionary: dict update someVar OuterKey temp { dict with temp { # Some script goes in here... } } # Alternative version using a key with 'dict with'... dict with someVar OuterKey { # Some script goes in here... } # Reference Implementation See SF patch 1008768<http://sf.net/tracker/?func=detail&aid=1008768&group_id=10894&atid=310894> . # Copyright This document has been placed in the public domain. |
Name change from tip/213.tip to tip/213.md.
|
| < | < | | | | | | | | | | > | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 213: A Standard Dialog for Font Selection Author: Donal K. Fellows <[email protected]> Author: Pat Thoyts <[email protected]> State: Withdrawn Type: Project Vote: Pending Created: 21-Aug-2004 Post-History: Keywords: Tk Obsoleted-By: 324 Tcl-Version: 8.6 ----- # Abstract This TIP proposes a new command that pops up a dialog box that allows the selection of a font. Where possible, this dialog will be implemented using the host platform's standard dialogs. # Rationale A number of platforms \(Windows and MacOSX\) have standard dialogs for common user-oriented tasks, and Tk provides an interface to these dialogs through commands such as _tk\_getOpenFile_ and _tk\_chooseColor_. However, another dialog that they provide and which some programs would find useful is a font selector. This TIP proposes adding a command to do just that; where a platform does not provide such a standard dialog, one implemented using a Tcl script will be used instead. # Proposed Change Tk shall have a new command, **tk\_chooseFont**, with the syntax described below \(which should be recognizably similar to **tk\_chooseColor**\). The dialog will not return a result as on some platforms \(MacOSX\) this is required to be modeless while on others \(Windows\) it must be modal. Therefore all actions will be done via an _-apply_ command. In the modal case clicking either the _Apply_ button \(if present\) or the _OK_ button will cause the _-apply_ command to be called with the font specification appended as an additional argument. If _Cancel_ is chosen then this is not called. For the modeless \(MacOSX\) case calling the _tk\_chooseFont_ command will cause the dialog to be displayed and closing the dialog will just withdraw it. > **tk\_chooseFont** ?_-option value -option value ..._? Permitted options are: -parent: This specifies the parent window of the dialog \(similarly to the **-parent** option to other dialogs\). -title: This specifies the title of the dialog. If the platform specific dialog cannot support this then the option is ignored. -initialfont: This specifies the initial font in any form given on the font\(n\) manual page \(section "FONT DESCRIPTION"\). Provided it is supported by the platform implementation this font will be selected when the dialog is displayed. -apply: This specifies a command prefix to be called when a font selection has been made by the user. The command will have the font specification appended as the final parameter and is then evaluated in the global namespace. The font specification will be a list of the form described on the font\(n\) manual page under "FONT DESCRIPTION" section 3. That is a list of \{family size style ?style ...?\} Whenever a platform provides a suitable font dialog in its own API, Tk should not use a script-based alternative, even if this means missing out on features like the title or dynamic updating of the font during the selection process. User code should not expect to receive a result from _tk\_chooseFont_ and may not assume that the dialog has been withdrawn or closed when the command returns. # Reference Implementation <http://sourceforge.net/support/tracker.php?aid=1477426> # Copyright This document has been placed in the public domain. |
Name change from tip/214.tip to tip/214.md.
|
| < | < | | | | | | | | | | > | | | | | | | | | | | | | > | 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 | # TIP 214: Add New Object Introspection Command Author: Ulrich Schöbel <[email protected]> Author: Larry W. Virden <[email protected]> State: Withdrawn Type: Project Vote: Pending Created: 24-Aug-2004 Post-History: Keywords: Tcl,info,representation Tcl-Version: 8.7 Obsoletes: 117 ----- # Abstract This TIP proposes the new **representation** subcommand to **info** which returns the internal representation of a variable's contents. # Rationale Inspired by a posting on news:comp.lang.tcl by Victor Wagner, I considered a facility to obtain the internal representation of the value of a variable to be useful. * It further extends the Tcl introspection commands. * It offers a method to check the type of a variable without conversion. * During the development process it is useful to detect/avoid shimmering and its negative performance effects. # Proposed Change Add the new subcommand **info representation** with the following syntax: > **info representation** _varName_ It returns the type of the variable _varName_ or an error, if * _varName_ doesn't exist, * _varName_ is an array and no index is provided, * _varName_ is a scalar variable but an index is provided. # Implementation A patch against Tcl8.4.6 is available <http://sf.net/support/tracker.php?aid=1015338> . # Copyright This document has been placed in the public domain. |
Name change from tip/215.tip to tip/215.md.
|
| < | < | | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | < | > | | | | | | < > | < > | | | | | | | | | | | | | | | > | 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 | # TIP 215: Make [incr] Auto-Initialize Undefined Variables Author: Andreas Leitgeb <[email protected]> Author: Don Porter <[email protected]> State: Final Type: Project Vote: Done Created: 25-Aug-2004 Post-History: Keywords: Tcl Tcl-Version: 8.5 ----- # Abstract Unlike **append** and **lappend**, **incr** currently does not auto-create yet-undefined variables. This TIP proposes to make **incr**'s behaviour in this regard more like the aforementioned commands. # Rationale A quite common task is counting the number of occurrences of items in a given list. The usual solution is to iterate the list, and for each item, increment the associated value in a tcl-array. As of now this requires a separate step of determining the not-yet-existence and eventual initialization to 0 or alternatively **catch**'ing errors from **incr** and setting the variable, if an error was raised. If we instead alter **incr** to treat non-existant variables as if they contained the value 0, this would be more like the auto-initializing behaviour of **append** and **lappend**, and would make writing code that does this sort of summing up much easier. It is also very similar to the way that the **dict incr** subcommand operates. # No Change for Variables that Contain Non-Integers Just as **lappend** does complain if passed a variable whose value is an invalid list \(e.g. a single open-brace\), so it appears reasonable for **incr** to still throw an error if the variable contains something that is not a number. The empty string is invalid as an operand for **expr**'s integer operators, so it should remain illegal to **incr** an existing variable that contains an empty string. # Further Special Cases If a variable passed to incr is not yet existing, but linked to some other not-yet existing var, or if it is traced, then of course it would add flesh to that existing husk. Care should be taken that any write traces only trigger once \(like for **lappend**\), not twice \(as in: for initializing and then for incrementing\). # Proposal The current **incr** command behaves like the following proc: proc incr {varName {increment 1}} { upvar 1 $varName v return [set v [expr {$v + $increment}]] ;# read/write trace } It is proposed to make **incr** behave like the following modified proc: proc incr {varName {increment 1}} { upvar 1 $varName v set code [catch {set v} value] ;# read trace if {$code} { return [set v $increment] ;# write trace } return [set v [expr {$value + $increment}]] ;# write trace } Please note these example procs are meant to illustrate the proposed change only. They do not fully reflect the exact function of **incr** \(limiting to only integer values, for example\). For a more concrete illustration of the proposal, see the reference implementation, SF patch \#1413115 <http://sourceforge.net/tracker/index.php?func=detail&aid=1413115&group_id=10894&atid=310894> . # Discussion There have been comments that **incr** modified as proposed would lose one means of typo-detection: If the varname is mistyped, then instead of throwing an error, it would turn into a noop. My \(TIP-originator\) answer to this: relying on thrown exceptions for mistyped varnames is a very weak strategy in dynamic \(non-compiled\) languages like tcl, anyway, because it would require a 100%-test-coverage of execution-paths. Nevertheless, this shouldn't exclude discussion about less typo-forgiving alternatives: Proposed \(by others\) alternative \#1: make **incr** accept a second optional argument _init_ which, if specified, will cause **incr** to accept non-existent variables and initialize them with the value _init_. One disadvantage of this behaviour is, that it is at odds with append and lappend behaviour, which would rather imply that if more than one argument is given after the varname, then each of them would be added in row. Another con would be, that it would not be intuitive, whether the resulting value would be _init_ or \(_init_ \+ _increment_\). Similar alternatives mentioning new option **-initValue** are over-verbose imho. Another way to partially reduce this proposal's forgiveness would be to allow autoinitialization only for array-elements. This looks grossly unorthogonal at first sight, but addresses the fact, that the primary reason for TIP 215 was counting occurrences of strings, which are then made keys in an array. The danger of mistyped array-keys is surely much lower than that of mistyped variable names. See [[224]](224.md) # Copyright This document has been placed in the public domain. |
Name change from tip/216.tip to tip/216.md.
|
| < | < | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | < > | | | | < < | > > | | | | | | | | | > | 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 | # TIP 216: Handling Command-Line Options in Tclsh and Wish Author: Arjen Markus <[email protected]> State: Draft Type: Project Vote: Pending Created: 23-Aug-2004 Post-History: Tcl-Version: 8.7 Keywords: Tcl, debugging, argument, shell ----- # Abstract Currently there is no means to add new command-line options to the standard Tcl shells, tclsh and wish, that can be handled at the script level. This hampers the development of, for instance, a scripted debugger or tracing tool, because the shell must be called with an awkward command line \(stating the location of the script file implementing the facility\). This TIP proposes a simple mechanism so that a command line like "tclsh -debug myprog.tcl" is possible. The new mechanism relies on the existing package mechanism and a few conventions. It can be implemented for the most part in Tcl. # Rationale With Tcl 8.4 it is quite easy to create a scripted debugger - see for instance <http://wiki.tcl.tk/6007> and <http://wiki.tcl.tk.12251> - since this version introduced execution traces. However, it is less simple to turn that into an "out-of-the-box" resource: suppose its implementation file is "debug.tcl", residing in a directory "~/my-tcl-utils" \(or "d:\\my-tcl-utils" under Windows\), then the following command-line is necessary: tclsh ~/my-tcl-utils/debug.tcl myapp.tcl or under Windows: tclsh d:\my-tcl-utils\debug.tcl myapp.tcl instead of the more elegant: tclsh -debug myapp.tcl where some mechanism links the option "-debug" to the implementation file "debug.tcl". An alternative method could be to make the file "debug.tcl" a loadable package but this requires the user to change the application: it should then load the debug package whenever the user wants to interactively debug it. # Proposed Changes The only thing that needs to be changed in tclsh and wish \(_TclMain.c_ and _TkMain.c_ respectively\) or any other shell to benefit from this new feature is that just before sourcing the file given on the command-line or going into an interactive loop, is that a new procedure is called, "HandleCmdLine" \(and some proper processing of its results\). This procedure, which will reside in _init.tcl_, does the following \(at least in the proposed, default, implementation\): * it loops over the command-line arguments \(in the global variable _argv_\): if the argument starts with "-", it is considered an option \(and it is removed from _argv_\). * the option is translated into the name of a package that gets loaded. * if the initialisation code of the package recognises other arguments, it must remove them from the list contained in _argv_. * this continues until an argument is found that does not qualify as an option. A simple implementation of this procedure is: proc HandleCmdLine {} { while { [string index [lindex $::argv 0]] == "-" } { set pkg [string range [lindex $::argv 0] 1 end] package require $pkg set ::argv [lrange $::argv 1 end] } if { [llength $::argv] > 0 } { set ::argv0 [lindex $::argv 0] set ::argv [lrange $::argv 1 end] } } \(Details like proper error handling are left out for simplicity.\) After the call to this procedure in the C code, variable _argv0_ must be examined to determine if the shell is to be run interactively or not. With the proposed mechanism, tclsh or wish can be invoked with: tclsh -debug myapp.tcl or: tclsh -trace -out "report.out" myapp.tcl \(assuming that the package trace recognises the option -out\) or: wish -tkcon myapp.tcl \(assuming Tkcon has been turned into a package\) # Reference Implementation None yet. # Copyright This document is placed in the public domain. |
Name change from tip/217.tip to tip/217.md.
|
| < | < | | | | | | | | > | | | | | | | | | | | | | < | > | | | | | | | | | | < > | | | < > | < | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 217: Getting Sorted Indices out of Lsort Author: James P. Salsman <[email protected]> State: Final Type: Project Vote: Done Created: 26-Aug-2004 Post-History: Keywords: Tcl,lsort,parallel lists Tcl-Version: 8.5 ----- # Abstract An **-indices** option is proposed for the **lsort** command, returning the indices of the given list's elements in the order that they would have otherwise been sorted. # Rationale When corresponding parallel lists must be simultaneously sorted or accessed in the order given by sorting them all according to one used as a list of keys, it is necessary to obtain the indices of the key list's elements in the order that they would be sorted, without actually sorting the list. For example, a list of first names and a corresponding list of last names can be displayed in side-by-side Tk listboxes, in which case we may want to sort both lists by either one used as the sorting key, or we may want to simultaneously iterate over both in either order. To do so, merely sorting a list is unhelpful; we need to obtain the indices of the key list in the order that its corresponding elements would be sorted. Tk listboxes, database I/O, and statistics applications often involve heavy use of parallel lists. For this and other reasons, many programming languages starting at least as early as APL, up to present-day, numerics-oriented languages such as MATLAB, have included the ability to directly obtain the indices required to access a list \(or "vector"\) in sorted order. As shown below, the fastest known pure Tcl solution to this problem takes about five times as long as the given reference implementation, which adds virtually no overhead when it is not invoked. # Specification The **lsort** command may accept a new option, **-indices**. When **lsort** is invoked with this option, it will return a list of integer indices of the elements of the list given as the final argument to **lsort**, in the order that the elements would have been sorted had the **-indices** option not been specified. This means an alternative \(though less efficient for single lists\) mechanism for producing a sorted list could be: set resultList [list] foreach idx [lsort -indices $sourceList] { lappend resultList [lindex $sourceList $idx] } # Reference Implementation The reference implementation is available from SourceForge <http://sourceforge.net/tracker/index.php?func=detail&aid=1017532&group_id=10894&atid=310894> It may need to be applied with **patch -l** or **patch --ignore-whitespace** or it may not apply entirely. That reference implementation is a 109-line context diff, involving adding 20 lines of code to _tclCmdIL.c_, a single auto int of new variable memory overhead, and no more than three additional integer comparisons and one integer assignment per use of **lsort** if the new option is not invoked. Compared to the following pure Tcl implementation, the reference implementation is 2.4 to 6.7 times faster. This very efficient Tcl implementation was provided by Lars Hellström: proc lsort-indices {itemL} { set pairL [list] foreach item $itemL { lappend pairL [list $item [llength $pairL]] } set indexL [list] foreach pair [lsort -index 0 -real $pairL] { lappend indexL [lindex $pair 1] } set indexL } The following timing data are the mean **time** returned from 20 different lists of random reals, with 10 iterations each: List size Ref. Imp. Pure Tcl Speedup --------- --------- -------- ------- 100 13.1 47.9 3.7 200 33.9 224.1 6.6 300 45.0 303.1 6.7 400 62.0 360.6 5.8 800 142.3 655.0 4.6 1600 486.2 1150.0 2.4 5000 1582.5 4847.6 3.1 At present, the Reference Implementation does not file the **-indices** switch alphabetically in the C list of **lsort** switches, or the C switch statement that interprets them. This simple needs to be corrected before final check-in. # Suggested Documentation In the **lsort** man page, under **DESCRIPTION**, change the first sentence: > "This command sorts the elements of list, returning a new list in sorted order." ... to read: > "This command sorts the elements of list, and returns a new list in sorted order, unless the -indices option is specified, in which case a list of integers is returned, corresponding to the indices of the given list's elements in the order that they otherwise would have been sorted." Under **EXAMPLES**, at the end of the section, include the following lines: Obtaining ordered indices: % lsort -indices [list a c b] 0 2 1 % lsort -indices -unique -decreasing -real -index 0 \ {{1.2 a} {34.5 b} {34.5 c} {5.6 d}} 2 3 0 # Tcl-core Discussion Here are some highlights from the discussion of this TIP on the Tcl-core mailing list. No assurance is given that the discussion is either completely or impartially represented here. Lars Hellström <http://sourceforge.net/mailarchive/message.php?msg_id=9346824> described a pure Tcl solution virtually identical to the one shown above, "which could be complicated enough to warrent a special [lsort] option." He also suggested a **-keycommand** option for sorting on keys generated on-the-fly. Finally, he pointed out a flaw concerning the example in the Rationale from the original version of this TIP, which has since been corrected. In reply to Lars, James Salsman <http://sourceforge.net/mailarchive/message.php?msg_id=9348381> provided timing data and an efficient alternative to the **-keycommand** idea using this TIP's **-indices** proposal. # Acknowledgements Thanks also to George Peter Staplin and Richard Suchenwirth for their kind help and good ideas at the genesis of this TIP. # Copyright This document has been placed in the public domain. |
Name change from tip/218.tip to tip/218.md.
|
| < | < | | | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 218: Tcl Channel Driver Thread State Actions Author: Andreas Kupries <[email protected]> Author: Andreas Kupries <[email protected]> Author: Larry W. Virden <[email protected]> Author: David Gravereaux <[email protected]> State: Final Type: Project Vote: Done Created: 09-Sep-2004 Post-History: Tcl-Version: 8.5 ----- # Abstract This document specifies a modification of the public definition of channel drivers for the Tcl I/O system to fix a bug in the transfer of channels between threads affecting all drivers requiring thread-specific initialization. The targets for the change are Tcl 8.4._x_ \(note that this is an API change to a release\) and Tcl 8.5. # Background and Motivation The purpose of this TIP is to address and solve a general problem exposed through the actual usage of the ability to transfer any channel between threads. Note that this ability was introduced into the Tcl core before TIPs were used to manage major changes, therefore it is not possible for us here to refer to a TIP. The relevant entry in the Tcl core ChangeLog is of 02-May-2000. The specific instance of the general problem is logged as SourceForge tracker item 952332<http://sf.net/support/tracker.php?aid=952332> \(a Feature Request in the IOCPSock project\). The Socket Channel Driver in the core maintains state not only per channel, but on Windows also per thread. This thread specific state is initialized during the first usage of the **socket** command at the script-level, i.e. _Tcl\_SocketObjCmd\(\)_ at the C-level. The relevant internal function for this is _TclpHasSockets\(\)_. This causes problems when transferring a socket channel into a thread which has not performed any socket operation before, as the per-thread state of the driver is **not** initialized at all in that case, causing a crash when trying to use the transfered channel. This is a general problem all channel drivers maintaining per-thread state will run into. And on Windows most channel drivers will **have to** maintain per-thread state. This is imposed by the design of the Tcl Notifier. It manages Event Sources on a per-thread basis, and this implies that the Event Source for channel drivers has to maintain, per-thread, a list of the channels belonging to a thread to make setup and checking for events efficient. A process global list would be possible, but would also not be very fast, as it would require locking for each search through it, and such searches happens per iteration per active eventloop per Tcl thread. What is needed is some way to initialize the thread-specific state of a channel driver for a specific thread, whenever a channel is created within that thread, independent of the method of creation. This can be solved without API changes, if we would restrict ourselves to the channel drivers in the core. This however would make non-core channel drivers second class. To avoid this an official public API is required. Note that the currently used fix in both 8.4 and 8.5 is an ad-hoc solution without API changes, making external drivers second class. In 8.4 the ad-hoc solution is even incomplete, not covering the sockets, only files. This TIP has been written to remedy this deficiency for both 8.4 and 8.5. # Specification It is possible to solve the specific problem described in the last chapter, by calling the relevant internal function, either in each low-level socket operation, or during the transfer itself. The first will slow down all socket operations \(one additional check for per-thread initialization per operation \(read, write, seek, ...\)\), the second introduces code specific to channel types into the transfer code. Neither solution is considered acceptable; they are mere band-aids. Instead of using one of the band-aids described above, this TIP proposes to solve the general problem of per-thread channel driver initialization by extending the public structure of channel drivers with one new function pointer. The purpose of this function is not directly the initialization of per-thread information, but to provide the driver with notifications when a channel of its type is removed from or added to a thread, by whatever means \(creation, deletion, transfer, ...\). This can be used not only to initialize the per-thread data of the channel driver, but for other thread-specific actions of the driver as well. As we are modifying a public structure, we have to distinguish between older drivers not supporting the new function and new drivers which do. The 'Tcl\_ChannelType' structure contains a version field just for this purpose. Currently known versions of drivers are version 0 to 3, where version 0 is for drivers whose structure does not contain a version field. The modification proposed in this document now introduces channel driver version 4. ## Details The definition of the new version tag is #define TCL_CHANNEL_VERSION_4 ((Tcl_ChannelTypeVersion) 0x4) The signature of the new function is void Tcl_DriverThreadActionProc (ClientData instanceData, int action); /* Codes for 'action' */ #define TCL_CHANNEL_THREAD_INSERT (0) #define TCL_CHANNEL_THREAD_REMOVE (1) The _Tcl\_DriverThreadActionProc_ defined for a channel type _FOO_ will be called by the core with thread _BAR_ as current thread whenever: 1. a channel of type _FOO_ is created in thread _BAR_. 1. a channel of type _FOO_ is transfered into the thread _BAR_. 1. a channel of type _FOO_ is closed in thread _BAR_. 1. a channel of type _FOO_ is transfered out of the thread _BAR_. For the first two calls we can assert _action == TCL\_CHAN\_THREAD\_INSERT_, and the last two calls can assert _action == TCL\_CHAN\_THREAD\_REMOVE_. Note that multiple calls of _Tcl\_DriverThreadActionProc_ per thread are possible and have to be dealt with correctly. The new definition of structure _Tcl\_ChannelType_ is typedef struct Tcl_ChannelType { [... Existing Definition ...] /* * Only valid in TCL_CHANNEL_VERSION_4 channels or later */ Tcl_DriverThreadActionProc *threadActionProc; /* Procedure to call to notify * the driver of thread specific * activity for a channel. * May be NULL. */ } Tcl_ChannelType; A new public accessor API is provided as well, returning a pointer to the new function \(or NULL if it does not exist\). Tcl_DriverThreadActionProc * Tcl_ChannelThreadActionProc(Tcl_ChannelType* typePtr); # Discarded Solutions It was initially proposed to extend the driver structure with a function having only a very narrow purpose- the initialization of the thread specific data of the driver. This was dropped because the solution actually proposed is more general and thus should be more stable in the long term. In other words, we believe that the adoption of the general solution reduces the risk of having to extend the Channel driver API again in the future, compared to the risk of this should we adopt the narrow solution. Another approach uses the same model as specified here, i.e. general cut and splice functionality, but uses two driver functions to implement this. The problem with this approach is that an implementor of a driver might get confused and realize only one of the two functions, i.e. only part of the required functionality. # Reference Implementation A reference implementation is provided at SourceForge <http://sourceforge.net/support/tracker.php?aid=875701> . # Comments David Gravereaux has recently tested this with his IOCPSOCK extension \(11/26\) and found no problems. If it hastens the acceptance of the TIP, David does not need the one export in the patch \(_Tcl\_DriverThreadActionProc_\) to be exported for his extension to work. Others that do channel chaining \(windows expect, for example\), will most likely need it. # Copyright This document has been placed in the public domain. |
Name change from tip/219.tip to tip/219.md.
|
| < | < | | | | | | | | > | | | | | | | | | 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 | # TIP 219: Tcl Channel Reflection API Author: Andreas Kupries <[email protected]> Author: Andreas Kupries <[email protected]> State: Final Type: Project Vote: Done Created: 09-Sep-2004 Post-History: Tcl-Version: 8.5 ----- # Abstract This document describes an API which reflects the Channel Driver API of the core I/O system up into the Tcl level, for the implementation of channel types in Tcl. It is built on top of [[208]](208.md) \('Add a chan command'\) and also an independent companion to [[230]](230.md) \('Tcl Channel Transformation Reflection API'\) and [[228]](228.md) \('Tcl Filesystem Reflection API'\). As the later TIPs bring the ability of writing channel transformations and filesystems in Tcl itself into the core so this TIP provides the facilities for the implementation of new channel types in Tcl. This document specifies version _1_ of the channel reflection API. # Motivation / Rationale The purpose of this and the other reflection TIPs is to provide all the facilities required for the creation and usage of wrapped files \(= virtual filesystems attached to executables and binary libraries\) within the core. While it is possible to implement and place all the proposed reflectivity in separate and external packages, this however means that the core itself cannot make use of wrapping technology and virtual filesystems to encapsulate and attach its own data and library files to itself. This is something which is desirable as it can make the deployment and embedding of the core easier, due to having less files to deal with, and a higher degree of self-containment. |
︙ | ︙ | |||
44 45 46 47 48 49 50 | give users of the core the freedom to experiment with their own ideas, instead of constraining them to what we managed to envision. Another use for reflected channels was found when creating the reference implementation: As helper for testing the generic I/O system of Tcl, by creating channels which forcibly return errors, bogus data, and the like. | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 | give users of the core the freedom to experiment with their own ideas, instead of constraining them to what we managed to envision. Another use for reflected channels was found when creating the reference implementation: As helper for testing the generic I/O system of Tcl, by creating channels which forcibly return errors, bogus data, and the like. # Specification ## Introduction This specification has to address two questions to make the reflection work. * How are the driver functions reflected into the Tcl level? * How are file events generated in the Tcl level communicated back to the C level? This includes routing to the correct channel. ## C Level API Four functions are added to the public C API. See section "_Error Handling_" for their detailed specification. ## Tcl Level API The Tcl Level API consists of two new subcommands added to the ensemble command **chan** specified by [[208]](208.md). The new subcommands are: * **chan create** _mode cmdprefix_ > This subcommand creates a new script level channel using the command prefix _cmdprefix_ as its handler. The _cmdprefix_ has to be a list. The API this handler has to provide is specified below, in the section "Command Handler API". The handle of the new channel is returned as the result of the command, and the channel is open. Use the regular **close** command to remove the channel. > The argument _mode_ specifies if the channel is opened for reading, writing, or both. It is a list containing any of the strings **read** or **write**. The list has to have at least one element, as a channel you can neither write to nor read from makes no sense. The handler command for the new channel has to support the chosen mode. An error is thrown if that is not the case. > We have chosen to use _late binding_ of the handler command. See the section "_Early versus Late Binding of the Handler Command_" for more detailed explanations. * **chan postevent** _channel eventspec_ > This subcommand is for use by command handlers, it notifies the channel represented by _channel_ that the event\(s\) listed in the _eventspec_ have occurred. The argument _eventspec_ is a list containing any of **read** and **write**. At least one element is required \(It does not make sense to invoke the command if there are no events to post\). > Note that this subcommand can be used only on channel handles which were created/opened with the subcommand **create**. Application to channels like files, sockets, etc. is not possible and will cause the generation of an error. > As only the Tcl level of a channel, i.e. its command handler, should post events to it we also restrict the usage of this command to the interpreter the handler command is in. In other words, posting events to a reflected channel from a different interpreter than its implementation is in is not allowed. > Another restriction is that it is not possible to post events the I/O core has not registered interest in. Trying to do so will cause the method to throw an error. See the method **watch** in section "Command Handler API" as well. ## Command Handler API The Tcl-level handler command for a reflected channel is an ensemble that has to support the following subcommands, as listed below. Note that the term _ensemble_ is used to generically describe all command \(prefixes\) which are able to process subcommands. This TIP is _not_ tied to the recently introduced 'namespace ensemble's. Of the available methods the handler **has to** support **initialize**, **finalize**, and **watch**, always. The other methods are optional. * _handlerCmd_ **initialize** _channel mode_ > This is the first call the command handler will receive for the given new _channel_. It is his responsibility to set up any internal data structures it needs to keep track of the channel and its state. > The return value of the method has to be a list containing the names of all methods which are supported by this handler. This implicitly tells the C level the version of the API used by the command handler making a separate version number redundant. Hence our decision to leave such a number out of the API. Any changes to the API will be either the elimination of methods, or the introduction of new ones. An existing method cannot change its signature \(arguments, and result\), a new method has to be introduced for this. All of this implies that this method, **initialize**, **is unchangeable** after the TIP has been committed, as it is the entry point through which the C level will determine the API version before it knows anything else. > Any error thrown by the method will abort the creation of the channel and no channel will be created. The thrown error will appear as error thrown by **chan create**. > Any exception beyond _error_, like _break_, etc. is treated as and converted to an error. > **Important** - If the creation of the channel was aborted due to failures in **initialize** then the method **finalize** will _not_ be called. > This method has no equivalent at the C level. > It was considered to return only the list of optional methods supported by the handler. The chosen method however should make the code in the C layer more regular. Another advantage of this is that it allows the C level to better check if the API it expects is matching the API provided by the handler. > The argument _mode_ tells the handler if the channel was opened for reading, writing, or both. It is a list containing any of the strings **read** or **write**. The C-level doing the call will never generate abbreviations of these strings. The list will always contain at least one element, as a channel you can neither write to nor read from makes no sense. > The method has to throw an error if the chosen mode is not supported by the handler command. * _handlerCmd_ **finalize** _channel_ > The method is called when the channel was **close**d, and is the last call a handler can receive for the given _channel_. This happens just before the destruction of the C level data structures. Still, the command handler must not access the channel anymore in no way. It is now his responsibility to clean up any internal resources it allocated to this channel. > The return value of the method is ignored. > If the method throws an error the command which caused its invocation \(usually **close**\) will appear to have thrown this error. > Any exception beyond _error_, like _break_, etc. is treated as and converted to an error. > The equivalent C-level function is _Tcl\_DriverCloseProc_. > This method is not invoked if the creation of the channel was aborted during **initialize**. * _handlerCmd_ **read** _channel count_ > This method is _optional_. It is called when the user requests data from a channel. _count_ specifies how many _bytes_ have been requested. If the method is not supported then it is not possible to read from the channel handled by the command. > The return value of the method is taken as the requested data. If the returned data contains more bytes than requested an error will be signaled and later thrown by the command which performed the read \(usually **gets** or **read**\). Returning less bytes than requested is acceptable however. > If the method throws an error the command which caused its invocation \(usually **gets**, or **read**\) will appear to have thrown this error. > Any exception beyond _error_, like _break_, etc. is treated as and converted to an error. > The equivalent C-level function is _Tcl\_DriverInputProc_. * _handlerCmd_ **write** _channel data_ > This method is _optional_. It is called when the user writes data to the channel. Note that the _data_ are bytes, not characters \(The underlying Tcl\_ObjType is _ByteArray_\). Any type of transformation \(EOL, encoding\) configured for the channel has already been applied at this point. If the method is not supported then it is not possible to write to the channel handled by the command. > The return value of the method is taken as the number of bytes written by the channel. Anything non-numeric will cause an error to be signaled and later thrown by the command which performed the write. A negative value implies that the write failed. Returning a value greater than the number of bytes given to the handler, or zero, is forbidden and will cause the C level to throw errors. > If the method throws an error the command which caused its invocation \(usually **puts**\) will appear to have thrown this error. > Any exception beyond _error_, like _break_, etc. is treated as and converted to an error. > The equivalent C-level function is _Tcl\_DriverOutputProc_. * _handlerCmd_ **seek** _channel offset base_ > This method is _optional_. It is responsible for the handling of seek and tell requests on the channel. If it is not supported then seeking will not be possible for the channel. > _base_ is one of > \* **start** - Seeking is relative to the beginning of the channel. > \* **current** - Seeking is relative to the current seek position. > \* **end** - Seeking is relative to the end of the channel. > The base argument of the builtin **seek** command takes the same names. > The _offset_ is an integer number specifying the amount of _bytes_ to seek forward or backward. A positive number will seek forward, and a negative number will seek backward. > A channel may provide only limited seeking. For example sockets can seek forward, but not backward. > The return value of the method is taken as the \(new\) location of the channel, counted from the start. This has to be an integer number greater than or equal to zero. > If the method throws an error the command which caused its invocation \(usually **seek**\) will appear to have thrown this error. > Any exception beyond _error_, like _break_, etc. is treated as and converted to an error. > The offset/base combination of 0/"current" signals a **tell** request, i.e. seek nothing relative to the current location, making the new location identical to the current one, which is then returned. > The equivalent C-level functions are _Tcl\_DriverSeekProc_, and _Tcl\_DriverWideSeekProc_ \(where possible\). * _handlerCmd_ **configure** _channel option value_ > This method is _optional_. It is for writing the type specific options. > Per call one option has to be written. > The return value of the method is ignored. > If the method throws an error the command which performed the \(re\)configuration or query \(usually **fconfigure**\) will appear to have thrown this error. > Any exception beyond _error_, like _break_, etc. is treated as and converted to an error. > The equivalent C-level function is _Tcl\_DriverSetOptionProc_. * _handlerCmd_ **cget** _channel option_ > This method is _optional_. It is used when reading a single type specific option. If this method is supported then the method **cgetall** has to be supported as well. > The call has to return the value of the specified option. > If the method throws an error the command which performed the \(re\)configuration or query \(usually **fconfigure**\) will appear to have thrown this error. > The equivalent C-level function is _Tcl\_DriverGetOptionProc_. * _handlerCmd_ **cgetall** _channel_ > This method is _optional_. It is used for reading all type specific options. If this method is supported then the method **cget** has to be supported as well. > It has to return a list of all options and their values. This list has to have an even number of elements. > If the method throws an error the command which performed the \(re\)configuration or query \(usually **fconfigure**\) will appear to have thrown this error. > Any exception beyond _error_, like _break_, etc. is treated as and converted to an error. > The equivalent C-level function is _Tcl\_DriverGetOptionProc_. * _handlerCmd_ **watch** _channel eventspec_ > This methods notifies the Tcl level that the specified channel is interesting in the events listed in the _eventspec_. This is a list containing any of **read** and **write**. The C-level doing the call will never generate abbreviations of these strings. The empty list is allowed as well and signals that the channel does not wish to be notified of any events. In other words, it has to disable event generation at the Tcl level. > Any return value of the method is ignored. This includes errors thrown by the method, break, continue, and custom return codes. > The equivalent C-level function is _Tcl\_DriverWatchProc_. > This method interacts with **chan postevent**. Trying to post an event not listed in the last call to this method will cause an error. * _handlerCmd_ **blocking** _channel mode_ > This method is _optional_. It handles changes to the blocking mode of the channel. The _mode_ is a boolean flag. True means that the channel has to be set to blocking. False means that the channel should be non-blocking. > The return value of the method is ignored. > If the method throws an error the command which caused its invocation \(usually **fconfigure**\) will appear to have thrown this error. > Any exception beyond _error_, like _break_, etc. is treated as and converted to an error. > The equivalent C-level function is _Tcl\_DriverBlockModeProc_. Notes: * The function _Tcl\_DriverGetHandleProc_ is not supported. There is no equivalent handler method at the Tcl level. * The function _Tcl\_DriverHandlerProc_ is not supported. There is no equivalent handler method at the Tcl level. The function has no relevance to base channels, which we work with here, only for channel transformations. See [[230]](230.md) \('Tcl Channel Transformation Reflection API'\) for more information on the issue. * The function _Tcl\_DriverFlushProc_ is not supported. The reason for this: The current generic I/O layer of Tcl does not use this function at all, nowhere. Therefore support at the Tcl level makes no sense either. We can always extend the API defined here \(and change its version number\) should the function be used at some time in the future. ## Error handling The current I/O core's ability to handle arbitrary Tcl error messages is very limited. _Tcl\_DriverGetOptionProc_ and _Tcl\_DriverSetOptionProc_ are the only driver functions for which this is possible directly. Everywhere else the API is restricted to returning POSIX error codes. This limitation makes the debugging of problems in a channel command handler at least very difficult. As such it is considered not acceptable. It is proposed to solve this problem through the addition of four new functions to Tcl's public stub table. > void **Tcl\_SetChannelError**\(Tcl\_Channel _chan_, Tcl\_Obj\* _msg_\) > void **Tcl\_SetChannelErrorInterp**\(Tcl\_Interp\* _ip_, Tcl\_Obj\* _msg_\) > > These functions store error information in a channel or interpreter. Previously stored information will be discarded. They have to be used by channel drivers wishing to pass regular Tcl error information to the generic layer of the I/O core. > > The refCount of _msg_ is unchanged when the functions had to rewrite _msg_ per the safety precautions explained below, as a properly modified copy of _msg_ is stored, and not _msg_ itself. Otherwise the refCount of _msg_ is incremented by one. > void **Tcl\_GetChannelError**\(Tcl\_Channel _chan_, Tcl\_Obj\*\* _msg_\) > void **Tcl\_GetChannelErrorInterp**\(Tcl\_Interp\* _ip_, Tcl\_Obj\*\* _msg_\) > > These function retrieve error information stored in a channel or interpreter O, and also resets O to have no information stored in it. They will return NULL if no information was stored to begin with. > > i.e. After an invocation of **Tcl\_GetChannelError\*** for a channel/interpreter object O, all following invocations will return NULL for that object, until an intervening invocation of **Tcl\_SetChannelError\*** again stored information in O. > > The _msg_ argument is not allowed to be NULL. Nor are the _chan_ and _ip_ arguments. > > The refCount of the returned information is not touched. The reference previously held by the channel or interpreter is now held by the caller of the function and it is its responsibility to release that reference when it is done with the object. This solution is not very elegant, but anything else will require an incompatible redefinition of the whole channel driver structure and of the driver functions. It should also be noted that usage of **Tcl\_Obj**ects for the information storage binds the information to a single thread. I.e. a transfer across thread boundaries is not possible. This however is not required here and thus no limitation. The four functions have been made public as I can imagine that even C level drivers might wish to use this facility to generate more explicit and readable error messages than is provided through POSIX error codes and the errno API. The information talked about in the API specifications above is **not** a plain string, but has to be a list of uneven length. The last element will be interpreted as the actual error message in question, and the preceding elements are considered as option/value pairs containing additional information about the error, like the _errorCode_, etc. I.e. they are an extensible dictionary containing the details of the error beyond the basic message. As a **safety precaution** any _-level_ specification submitted by the driver and a non-zero value will be rewritten to a value of _0_ to prevent the driver from being able to force the user application into the execution of arbitrary multi-level returns, i.e. from arbitrarily changing the control-flow of the application itself. Analogously any _-code_ specification with a non-zero value which is not _error_ is rewritten to value _1_ \(i.e. _error_\). Below a list of driver functions, and which of the _Tcl\_SetChannelError\*** functions they are allowed to use. * **Tcl\_DriverCloseProc** > May use _Tcl\_SetChannelErrorInterp_, and only this function. * **Tcl\_DriverInputProc** > May use _Tcl\_SetChannelError_, and only this function. * **Tcl\_DriverOutputProc** > May use _Tcl\_SetChannelError_, and only this function. * **Tcl\_DriverSeekProc**, and **Tcl\_DriverWideSeekProc** > May use _Tcl\_SetChannelError_, and only this function. * **Tcl\_DriverSetOptionProc** > Has already the ability to pass arbitrary error messages. Must **not** use any of the new functions. * **Tcl\_DriverGetOptionProc** > Has already the ability to pass arbitrary error messages. Must **not** use any of the new functions. * **Tcl\_DriverWatchProc** > Must **not** use any of the new functions. Is internally called and has no ability to return any type of error whatsoever. * **Tcl\_DriverBlockModeProc** > May use _Tcl\_SetChannelError_, and only this function. * **Tcl\_DriverGetHandleProc** > Must **not** use any of the new functions. It is only a low-level function, and not used by Tcl commands. * **Tcl\_DriverHandlerProc** > Must **not** use any of the new functions. Is internally called and has no ability to return any type of error whatsoever. Given the information above the following public functions of the Tcl C API are affected by these changes. I.e. when these functions are called the channel may now contain a stored arbitrary error message requiring processing by the caller. * **Tcl\_StackChannel** * **Tcl\_Seek** * **Tcl\_Tell** * **Tcl\_ReadRaw** * **Tcl\_Read** * **Tcl\_ReadChars** * **Tcl\_Gets** * **Tcl\_GetsObj** * **Tcl\_Flush** * **Tcl\_WriteRaw** * **Tcl\_WriteObj** * **Tcl\_Write** * **Tcl\_WriteChars** All other API functions are unchanged. Especially the functions below leave all their error information in the interpreter result. * **Tcl\_Close** * **Tcl\_UnregisterChannel** * **Tcl\_UnstackChannel** A previous revision of this TIP specified only two functions, storing the data only in channels. This however proved to be inadequate. It allows the transfer of messages for most driver functions, but not _close_. Storing an error message in the channel structure which is destroyed is not helpful. So we need the functions for storing data in interpreters. Conversely, providing only two functions storing the information in an interpreter, is inadequate as well. The circumstances for that to happen are actually very limited, but they can happen. First, most driver functions are not given an interpreter reference when called, and actually do not know which interpreter caused their invocation. The only remedy we have is that the channel structure has to have an interpreter reference to the interpreter of the command handler, for the calls into the Tcl level. This could be used in most circumstances, except when threads are enabled and the channel was transfered out of the thread containing that interpreter. We are not allowed to use this interpreter from the channel thread, and again have no other reference available. So for this the code/message pair has to be stored in a channel as the sole place available. A previous revision of this TIP not only stored an error message, but also a result code in the channel or interpreter, and used it as the return code of the Tcl command which invoked the driver function returning the exception. This feature has been discarded as a possible security hazard. It would allow a malicious Tcl driver to cause _break_ and _continue_ exceptions at arbitrary locations in the overall application, controlling its behaviour as it sees fit. I wish to thank Joe English and Vince Darley for their input with regard to the limitations of error propagation in the I/O core and possible ideas for solving it. Joe's discourse on the problems with the use of POSIX error codes in an earlier revision of this TIP made me realize that I should not use them anywhere in the API for reflected channels and rather concentrate on extending the I/O system to properly receive Tcl error messages. And while I rejected the **TclSetPosixError** function Vince proposed I hopefully kept the spirit of that proposal in my solution as well. The main reason against setting an arbitrary _posix error string_ was that it invented another way of passing error information around, whereas the specification above is based on the existing Tcl\_InterpState and attendant functionality. ## Interaction with Threads and Other Interpreters. A channel created with the **chan create** command knows the interpreter it was created in and executes its handler command only in that interpreter, even if the channel is shared with and/or has been moved into a different interpreter. This is easy to accomplish, by evaluating the handler command only in the context of the original interpreter. The channel also knows the thread it was created in and executes its handler command only in that thread, even if the channel has been moved into a |
︙ | ︙ | |||
600 601 602 603 604 605 606 | original thread, able to process these events. Note that this also allows the creation of a channel whose two endpoints live in two different threads and provide a stream-oriented bridge between these threads. In other words we can provide a way for regular stream communication between threads instead of having to send commands. | | | | | | | | | | | | | | | | | | | | | | | | | | | | | < > | | | | | < > | | | | | | | | | < > | | | | | | | < > | | | < | > | | | | | | | | | | | | | | > | 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 | original thread, able to process these events. Note that this also allows the creation of a channel whose two endpoints live in two different threads and provide a stream-oriented bridge between these threads. In other words we can provide a way for regular stream communication between threads instead of having to send commands. When a thread or interpreter is deleted all channels created with the **chan create** command using this thread/interpreter as their computing base will be deleted as well, in all interpreters they have been shared with or moved into, and in whatever thread they have been moved to. This pulls the rug out under the other thread\(s\) and/or interpreter\(s\), this however cannot be avoided. Trying to use such a channel will cause the generation of the regular error about unknown channel handles. ## Interaction with Safe Interpreters The new subcommands **create** and **postevent** of **chan** are safe and therefore made accessible to safe interpreters. While **create** arranges for the execution of code this code is always executed within the safe interpreter, even if the channel was moved \(See previous section\). The subcommand **postevent** can trigger the execution of fileevent handlers, however if they are executed in trusted interpreters then they were registered by these interpreters as well. \(Moving channels between threads strips fileevent handlers, and just between interpreters keeps them, and executes them where they were added\). ## Early versus Late Binding of the Handler Command We have two principal methods for using the handler command. These are called early and late binding. Early binding means that the command implementation to use is determined at the time of the creation of the channel, i.e. when **chan create** is executed, before any methods are called. Afterward it cannot change. The result of the command resolution is stored internally and used until the channel is destroyed. Renaming the handler command has no effect. In other words, the system will automatically call the command under the new name. The destruction of the handler command is intercepted and causes the channel to close as well. Late binding means that the handler command is stored internally essentially as a string, and this string is mapped to the implementation to use for each and every call to a method of the handler. Renaming the command, or destroying it means that the next call of a handler method will fail, causing the higher level channel command to fail as well. Depending on the method the error message may not be able to explain the reason of that failure. Another problem with this approach is that the context for the resolution of the command name has to be specified explicitly to avoid problems with relative names. Early binding resolves once, in the context of the **chan create** call. Late binding performs resolution anywhere where channel commands like **puts**, **gets**, etc. are called, i.e. in a random context. To prevent problems with different commands of the same name in several namespaces it becomes necessary to force the usage of a specific fixed context for the resolution. The only context suitable for such is the global context \(per _uplevel \#0_, not _namespace eval ::_\). Note that moving a different command into place after renaming the original handler allows the Tcl level to change the implementation dynamically at runtime. This however is not really an advantage over early binding as the early bound command can be written such that it delegates to the actual implementation, and that can then be changed dynamically as well. However, despite all this late binding is so far the method of choice for the implementation of callbacks, be they in Tcl, or Tk; and has been chosen for the reflection as well. ## Miscellanea The channel reflection API reserves the driver type "tclrchannel" for itself. Usage of this driver type by other channel types is not allowed. # Examples ## Driver Implementations A simple way of implementing new types of channels is to use any of the various object systems for Tcl. Create a class for the channel type. Create the new channel in the constructor for new objects and store the channel handle. Make the new object the command handler for the channel. This automatically translates the sub commands for the command handler into object methods. Implement the various methods required. when the object is deleted close the channel, and delete the object when the channel announces that it has been **close**d. This part is a bit tricky, flags have to be used to break the potential cycle. Another possibility is to implement the command handler as a regular command, together with a creation command wrapping around **chan create** and a backend which keeps track of all handles created by it and their state, associated data, etc. object based example ... snit::type new_channel { constructor {mode args} { # Handle args ... set chan [chan create $mode $self] } destructor { # ... delete internal state ... if {$dead} return set dead 1 close $chan } method handle {} {return $chan} variable chan variable dead 0 method finalize {dummy} { if {$dead} return set dead 1 $self destroy } method initialize {dummy mode} {} method read {dummy count} {} method write {dummy data} {} method seek {dummy offset base} {} method configure {dummy args} {} method watch {dummy events} {} method blocking {dummy isblocking} {} } proc newchannel_open {args} { return [[new_channel %AUTO% {expand}$args] handle] } ## Other Possible Drivers * Memory channel based on a string. Block and/or FIFO oriented. * Null device. Writable, not writable. WOM device. Data sink. * Random data \(Writing to it may re-seed the PRNG\). * Zero channel. Readable, returns a stream of binary 0s. Not writable. * FIFO channel between different threads. * Optimized virtual filesystem implementations. > Current VFS implementations have to use the package _memchan_ to provide the channels when a file in them is opened, which necessitates that for all open files all of their data is in memory, possibly even more than once \(when several channels are open on the same file\). A reflected driver however allows implementations which keep only part of the data in memory. Or nearly none at all if the VFS provides computed information / is based on some data structure. > A more concrete example would be a driver which provides access to files stored in some archive file. Using a reflect driver the archive file can be memory mapped and the driver will then read whatever data is needed when requested. Currently it will have to copy the data into a _memchan_ channel, i.e duplicate it in memory. > Note that of course the internals of the archive file may limit the amount of memory savings we can achieve. If for example the file we wish to access is stored in a compressed form we will have to decompress it in memory at least to the highest location requested so far. And any write operation \(if allowed\) will have to keep the data in memory until it has been compressed and committed. # Reference Implementation A reference implementation is provided at SourceForge <http://sourceforge.net/support/tracker.php?aid=1025294> . # Comments _[ Add comments on the document here ]_ # Copyright This document has been placed in the public domain. |
Name change from tip/22.tip to tip/22.md.
|
| < | < | | | | | | | | | | | | > | | | | | | | | | | | | | | | | < > | | | < < > > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 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 | # TIP 22: Multiple Index Arguments to lindex Author: David Cuthbert <[email protected]> Author: Kevin Kenny <[email protected]> Author: Don Porter <[email protected]> Author: Donal K. Fellows <[email protected]> State: Final Type: Project Vote: Done Created: 19-Jan-2001 Post-History: Discussions-To: news:comp.lang.tcl,mailto:[email protected] Keywords: lindex,multiple arguments,sublists Tcl-Version: 8.4a2 ----- # Abstract Obtaining access to elements of sublists in Tcl often requires nested calls to the _lindex_ command. The indices are syntactically listed in most-nested to least-nested order, which is the reverse from other notations. In addition, the nesting of command substitution brackets further decreases readability. This proposal describes an extension to the _lindex_ command that allows it to accept multiple index arguments, in least-nested to most-nested order, to automatically extract elements of sublists. # Rationale The heterogeneous nature of Tcl lists allows them to be applied to a number of useful data structures. In particular, lists can contain elements that are, themselves, valid lists. In this document, these elements are referred to as _sublists._ Extracting elements from sublists often requires nested calls to _lindex._ Consider, for example, the following Tcl script that prints the center element of a 3-by-3 matrix: set A {{1 2 3} {4 5 6} {7 8 9}} puts [lindex [lindex $A 2] 2] When these calls are deeply nested - e.g., embedded in an _expr_ arithmetic expression, having results extracted through _lrange,_ etc. - the results are difficult to read: # Print the sum of the center indices of two 3x3 matrices set p [expr {[lindex [lindex $A 2] 2] + [lindex [lindex $A 2] 2]}] # Get all but the last font in the following parsed structure: set pstruct {text {ignored-data { ... } } {valid-styles {justifiction {left centered right full}} {font {courier helvetica times}} } } return [lrange [lindex [lindex [lindex $pstruct 1] 2] 2] 0 end-1] Note that the list of indices in the latter example is listed in the reverse order of vector indices. In most other languages/domains, the last line might take on one of the following forms: return list_range(pstruct[2][2][1], 0, end-1); return pstruct[[2, 2, 1]][[0:-1]] temp = pstruct(2, 2, 1); result = range(temp, 0, length(temp) - 1); Allowing the _lindex_ command to accept multiple arguments would allow this more-natural style of coding to be written in Tcl. # Specification 1. Under this proposal, the syntax for the _lindex_ command is to be modified to accept one of two forms: lindex list indexList or lindex list index1 index2... > In either form of the command, the _list_ parameter is expected to be a well-formed Tcl list. > In the first form of the command, the _indexList_ argument is expected to be a Tcl list comprising one or more list indices, each of which must be an integer, the literal string _end_, or the literal string _end-_ followed by an integer with no intervening whitespace. The existing _lindex_ command is a degenerate form of this first form, where the list comprises a single index. > In the second form of the command, each of the _index_ arguments is expected to be a list index, which again may be an integer, the literal string _end_, or the literal string _end-_ followed by an integer with no intervening whitespace. 2. In either form of the command, once the _indexList_ parameter is expanded, there is a single _list_ parameter and one or more _index_ parameters. If there is a single _index_ parameter _N_, the behavior is identical to today's _lindex_ command, and the command returns the _N_th element of _list_; if _N_ is less than zero or at least the length of the list, a null string is returned. 3. If more than one _index_ parameter is given, then the behavior is defined recursively; the result of lindex $list $index0 $index1 ... > or lindex $list [list $index0 $index1 ...] > is indentical to that of lindex [lindex $list $index0] $index1... > or, equivalently, lindex [lindex $list $index0] [list $index1...] > \(This specification does not constrain the implementation, which may be iterative, recursive, or even expanded inline.\) 4. When an invalid index is given, an error of the form, _bad index "invalid\_index": must be integer or end?-integer?_, where _invalid\_index_ is the first invalid index encountered, must be returned. 5. If the list argument is malformed, the error resulting from an attempt to convert the list argument to a list must be returned. This behaviour is unchanged from the current implementation. # Side Effects 1. Whether the result of the _lindex_ operation is successful, the underlying Tcl\_Obj that represents the list argument may have its internal representation invalidated or changed to that of a list. # Discussion Some attention must be paid to giving the _lindex_ command adequate performance. In particular, the implementation should address the common case of lindex $list $i where _$i_ is a "pure" integer \(that is, one whose string representation has not yet been formed\). If the above specification is followed naively, the flow will be as follows. Since _objc_ is three, _objv[[2]](2.md)_ is expected to be a list. Since it is not, it must be converted from its string representation. It does not have one yet, so the string representation must be formed. Now the string representation is parsed as a list. An array \(of length one\) of Tcl\_Obj pointers is allocated to hold the list in question, and a Tcl\_Obj is allocated to hold the single element. Memory is allocated to hold the element's string representation. Now the _lindex_ command converts the first element of the list to an index \(in this case an integer\). This elaborate ballet of type shimmering requires converting the integer to a string and back again. It also requires four calls to _ckalloc:_ 1. Allocate a buffer for the string representation. 2. Allocate the array of Tcl\_Obj pointers for the list representation. 3. Allocate the Tcl\_Obj that represents the first \(and only\) element of the list. 4. Allocate a buffer for the string representation of that element. And at the end, the result is the same integer that was passed as a parameter originally. To avoid all this overhead in the common case, the proposed implementation shall \(in the case where _objc==3_\) 1. Test whether _objv[[2]](2.md)_ designates an object whose internal representation holds an integer. If so, simply use it as an index. 2. Test whether _objv[[2]](2.md)_ designates an object whose internal representation holds a list. If so, perform the recursive extraction of indexed elements from sublists described above. 3. Form the string representation of _objv[[2]](2.md)_ and test whether it is _end_ or _end-_ followed by an integer. If so, use it as an index. 4. Attempt to coerce _objv[[2]](2.md)_ to an integer; if successful, use the result as an integer. 5. Attempt to coerce _objv[[2]](2.md)_ to a list; if successful, use the result as an index list. 6. Report a malformed _index_ argument; the _indexList_ parameter is not a well-formed list. This logic handles all the cases of singleton lists transparently; it is effectively a simple-minded type inference that optimizes away needless conversions. Assuming that the related [[33]](33.md) is approved, this logic will most likely be combined with the identical logic required in that proposal for parsing _index_ arguments to the _lset_ command. ---- # Comments _Don Porter <[email protected]>_ > I agree that it would be helpful to many programmers to provide a multi-dimensional array data structure that can be accessed in the manner described in this TIP. In the _struct_ module of _tcllib_, several other data structures are being developed: graph, tree, queue, stack. I would support adding another data structure to that module that provides an interface like the one described in this TIP, with the intent that all of these helpful data structures find their way into the BI distribution. > I don't see any advantage to adding complexity to [lindex] as an alternative to development of a multi-dimensional array structure. Without a compelling advantage, I'm inclined against making [lindex] more complex. I like having Tcl's built-in commands provide primitive operations, and leave it to packages to combine the primitives into more useful, more complex resources. > This TIP should also consider how any changes to [lindex] mesh with the whole [listx] overhaul of Tcl's [list] command that has been discussed. _Dave Cuthbert <[email protected]> responds_ > Don makes a good point -- with a good set of data structures in tcllib, the need for this TIP is lessened or even eliminated. Nonetheless, I see this as a way of implementing the structures he describes. In other words, a more powerful primitive \(which, in reality, adds fairly little complexity when measured in number of lines of code changed\) would benefit these structures. > As for the [listx] overhaul, there are many competing proposals for the specification it is difficult to come up with a metric. In writing this TIP, I assumed a vacuum -- that is, a listx command would not be added to the core in the near future. _Donal K. Fellows <[email protected]> points out_ > Although there is tcllib and [listx] to think about, they are certainly not reasons for rejecting this TIP out of hand. The availability of tcllib is not currently anything like universal \(not stating whether this is a good, bad or ugly thing\) and all the [listx] work will need its own TIP to make it into the core \(you tend to have availability problems if it is an extension.\) It is not as if the core is short of syntactic sugar right now \(the [foreach] command is ample demonstration of this.\) _Don Porter <[email protected]> follows up_ > I'll leave the discussion above in place so the history of this TIP is preserved, but I have withdrawn my objection. ---- There was quite a discussion on news:comp.lang.tcl about using lindex to return multiple arguments. For example: % set list {a {b1 b2} c d e} % lindex $list 1 b1 b2 % lindex $list 1 0 {b1 b2} a % lindex $list {1 0} b1 In other words, the list index arguments can, themselves, be lists. Only when the argument is a list would the "recursive selection" procedure of the TIP be used. For multiple arguments, the behaviour is akin to lindex $list a b c -> list [lindex $list a] [lindex $list b] [lindex $list c] _Summarised by Dave Cuthbert <[email protected]>_ _Donal K. Fellows <[email protected]> points out_ > The problems with the above version of multiple indexing are that it loses the property that [lindex] always returns a single element \(making writing robust code harder\) and that it forces use of the [list] constructor a lot or inefficient type handling when some of the indices must be computed. Then there is the whole question of what happens when you have indexes that are lists of lists, which is a major can of worms. > Luckily, we could always put this sort of behaviour into a separate command \(e.g. called [lselect]\) which addresses at least the majority of my concerns, and which \(in my opinion\) need not even form part of this TIP. _Dave Cuthbert <[email protected]> adds_ > I intentionally left [lselect] out of the original TIP \(and it is still not present in the 02-April-2001 version\). As Donal points out, it is a major can of worms and, though there was general agreement on c.l.t that such a command would be useful, people had differing opinions on what form it should take. > Perhaps my view on TIPs is incorrect, but I try to include only sure-fire "yeah, we ought to have done that a few versions ago" items. ---- # Notes on History of this TIP _This TIP was originally written by Dave Cuthbert <[email protected]>, but ownership has passed \(beginning of April\) to Kevin Kenny <[email protected]>._ This TIP underwent substantial revision in May of 2001, to add the syntax where all the _index_ parameters could be grouped as a list rather than placed inline on the command line. # See Also [[33]](33.md). # Copyright This document has been placed in the public domain. |
Name change from tip/220.tip to tip/220.md.
|
| < | < | | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 220: Escalate Privileges in VFS Close Callback Author: Colin McCormack <[email protected]> Author: Andreas Kupries <[email protected]> Author: Vince Darley <[email protected]> State: Draft Type: Project Vote: Pending Created: 12-Sep-2004 Post-History: Tcl-Version: 8.7 ----- # Abstract This tip allows the creator and opener of a channel to cast away privileges and have them restored on close, to permit last-minute processing. It is sufficient to resolve a _tclvfs_ bug, minimal, and safe. # Abstract This tip allows the creator and opener of a channel to cast away privileges and have them restored on close, to permit last-minute processing. It is sufficient to resolve a _tclvfs_ bug, minimal, and safe. # Rationale _Tclvfs_ has a bug **[[1004273]](1004273.md)** _Can't read from channel in close callback_ <http://sourceforge.net/support/tracker.php?aid=1004273> that is due in part to the core channel handler behaviour. The problem is that the user has requested a read-only or write-only channel, but the _tclvfs_ close process absolutely requires fuller access to the channel. Use case one: A user's write-only channel has to be read by close in order to be processed. The second relevant use case: A user's read-only channel has to be written, i.e. loaded with data, before it is passed to the user. The first use case can be modelled by the _owner_ of a channel \(in this case, the _tclvfs_ code\) by opening it with minimal permissions, handing the channel to a user, then subsequently re-aquiring full possible channel permissions at the point where the channel needs to be closed - that is, immediately before the _tclvfs_ close callback is invoked. The second use case can be modelled by the _owner_ of a channel \(in this case, the _tclvfs_ code\) by opening it with maximal permissions, loading the data, and handing the channel to a user **after** removing the unwanted permissions from the channel. # Safety * Escalation of privilege is controlled with the Tcl core, and is unavailable to extensions except in their role as vfs implementations. * Privilege is only granted to the entity which opened the channel, because only that entity implements the close callback. * The creator/opener can't operate with any permissions it could not have obtained at creation/opening time, since they are granted by the OS and not Tcl. * Privilege escalation occurs only at a point immediately before the Tcl core is about to completely close the channel, so the privileges can't leak. * The operation of releasing privileges only restricts the user of a channel, it cannot be used to reaquire privileges which are not granted by the channel. # Proposed Changes Immediately prior to invoking the VFS close callback on a channel, Tcl core should set channel's permissions to the maximum possible. Export a new function as part of the public API which allows a user to remove privileges from channel, but not to add them. # Details The signature of the new function is int Tcl_RemoveChannelMode (Tcl_Interp* interp, Tcl_Channel chan, int mode); /* Codes for 'mode', already defined, _not_ new */ #define TCL_READABLE (1<<1) #define TCL_WRITABLE (1<<2) The argument _mode_ determines which privilege to release, and is set to one of the two specified codes. It is **not** a bitset. It is not allowed to release all privileges of the channel, as this would make the channel completely inacessible. Trying to do so will therefore cause the generation of an error, without changing the channel. The function will return a regular Tcl result code, either TCL\_OK, or TCL\_ERROR. If the _interp_ argument is set an error message will be left in the interp in the error case. If the _interp_ argument is NULL it will be ignored. # History This TIP was originally written to allow C code to modify permissions, but this makes the permissions system mean nothing, as a channel's permissions could then be freely modified in an _ad hoc_ manner. The TIP now specifies a weaker modification that is still powerful enough to implemenent the desired channel semantics. # Reference Implementation A reference implementation will be provided at SourceForge <http://sourceforge.net/support/tracker.php?aid=1057093> . # Comments It may be preferable for the new function to be in tclInt.h and therefore in the non-public interfaces \(tclvfs already makes use of tclInt.h anyway\): TclRemoveChannelMode. _[ Add more comments on the document here ]_ # Copyright This document has been placed in the public domain. |
Name change from tip/221.tip to tip/221.md.
|
| < | < | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 221: Allow Background Error Handlers to Accept Return Options Author: Don Porter <[email protected]> State: Final Type: Project Vote: Done Created: 15-Sep-2004 Post-History: Keywords: bgerror,return,options Tcl-Version: 8.5 ----- # Abstract This TIP proposes a new system for registering a background error handler of an interp so that the full set of return options \([[90]](90.md)\) can be passed to it. # Background Whenever a script is evaluated as part of handling an event, and that script evaluation returns TCL\_ERROR or some other non-TCL\_OK return code it is not equipped to handle, then the code that evaluates that script is expected to call _Tcl\_BackgroundError_ to report the exceptional code to the application. Then _Tcl\_BackgroundError_ will arrange for the command **bgerror** to be called during an idle event. It is intended that each application will define a **::bgerror** command to its liking so that background errors are reported \(or ignored\) as the application prefers. The defined syntax for **bgerror** is > **bgerror** _message_ The **bgerror** command receives as its only argument a copy of what the interp result was when _Tcl\_BackgroundError_ was called. This is presumably an error message. When **bgerror** is called, it is also arranged that the variables **::errorInfo** and **::errorCode** are set to the same values they had when _Tcl\_BackgroundError_ was called. This is effectively another set of arguments passed through a side channel. Note that the non-TCL\_OK return code that triggered the _Tcl\_BackgroundError_ call is not itself made known to **bgerror**. Nor is the _-level_, _-errorline_, or other return option information made possible by [[90]](90.md) passed along to **bgerror** in any way. # Proposal A new subcommand, **interp bgerror** will be created that allows for registration of a handler command to react to background errors. Its syntax will be: > **interp bgerror** _path_ ?_cmdPrefix_? Here _path_ is the path of an interp, interpreted the same way as the _path_ argument to the existing **interp aliases** subcommand. This argument determines which interp's background error handler we are interested in. The value of an empty list for _path_ indicates the current interp. As is the case with other **interp** subcommands, an alternative means to access the same functionality will be made available as the **bgerror** subcommand of the _slave_ command of an interp with syntax: > _slave_ **bgerror** ?_cmdPrefix_? When no _cmdPrefix_ argument is present, the command prefix currently registered to handle background errors in the _path_ interp will be returned. The returned value will be the _cmdPrefix_ argument most recently successfully passed to **interp bgerror** _path_, or the default background error handler command of the interp. When a _cmdPrefix_ argument is present, it must be a valid Tcl list of length at least one. An invalid list or an empty list is an error. A _cmdPrefix_ list argument of length _N_ will become the first _N_ substituted words of the handler command invoked to handle calls to _Tcl\_BackgroundError_. That is, if the _cmdPrefix_ argument is stored in a variable **cmdPrefix**, subsequent calls to _Tcl\_BackgroundError_ will lead to evaluation of a command like so: > **\{expand\}$cmdPrefix** _message_ _returnOptionsDictionary_ The _message_ argument is the interp result at the time _Tcl\_BackgroundError_ is called. The _returnOptionsDictionary_ argument is a Tcl dict value \([[111]](111.md)\) holding the value of the interp's return options dictionary at the time _Tcl\_BackgroundError_ was called. Specifically, the _returnOptionsDictionary_ argument is the value returned by _Tcl\_GetReturnOptions_ \([[227]](227.md)\) at the time _Tcl\_BackgroundError_ is called. Stored in the _returnOptionsDictionary_ argument will be values for the _-level_ and _-code_ keys, and when those values indicate a TCL\_ERROR triggered the _Tcl\_BackgroundError_ call, the _-errorinfo_, _-errorcode_, and _-errorline_ keys will have values as well. Any other return options present in the interp's return options dictionary at the time _Tcl\_BackgroundError_ is called will also be available in the _returnOptionsDictionary_ argument. Note that after this change, applications will be able to register a background error handling command that has no need to consult the variables **::errorInfo** or **::errorCode** at all. # Compatibility Existing applications making use of the **bgerror** interface provide a **bgerror** command that expects exactly one argument. To continue to compatibly support these applications, the default background error handler command prefix registered in each interp will be a command that sets the values of **::errorInfo** and **::errorCode** to the values of the corresponding keys in the return options dictionary, if appropriate. Then it will invoke the command **bgerror** _message_ in the global namespace. For complete compatibility, the existing fallbacks will also be honored in the default handler, including the invoking a hidden command **bgerror** _message_ in safe interps, and the ultimate fallback \(in trusted interps only\) being a message written to the stderr channel of the process as determined by _Tcl\_GetStdChannel\(TCL\_STDERR\)_. # Rejected Alternatives The first draft of this proposal proposed several attempts to call **bgerror**, first with two arguments, then with one. It was rejected because an error due to calling **bgerror** with the wrong number of arguments could not be distinguished \(easily and reliably\) from an error for other reasons. This fallback strategy was prone to the masking of errors. The new proposal is also preferred over the first draft as it empowers Tcl programmers to leave behind **bgerror** as a _magic_ command name with special significance to Tcl. Callback registration is a cleaner mechanism then giving particular command names privileged status, and we should move in that direction when the opportunity arises. An alternative syntax for **interp bgerror**, > **interp bgerror** _path target cmdPrefix_ was considered. This alternative would have allowed background errors in the _path_ interp to be handled in the _target_ interp. The difficulty with this alternative was in how to define the introspection form of the command. Introspection would need to return _target_ information, and it would be possible that the target interp of the handler would be an interp for which no _target_ path could be constructed to be returned \(a sibling, parent, or uncle interp, etc.\). The proposed form can be combined with **interp alias** to still allow background errors in one interp to \(ultimately\) be handled by a command evaluation in a different interp. # Reference Implementation See Tcl Patch 1060579. # Comments Please make any comments here. # Copyright This document has been placed in the public domain. |
Name change from tip/222.tip to tip/222.md.
|
| < | < | | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 222: Add [wm attributes -alpha] Attribute on Windows Author: Jeff Hobbs <[email protected]> Author: Andreas Kupries <[email protected]> State: Final Type: Project Vote: Done Created: 16-Sep-2004 Post-History: Tcl-Version: 8.5 Keywords: Tk ----- # Abstract This TIP proposes a new controlled attribute **-alpha** to control toplevel alpha transparency for the **wm attributes** command on Windows. # Rationale Windows 2000/XP\+ has the ability to create windows with alpha transparency. This attribute would expose control for that functionality for Tk users. This is mostly an eye candy feature, but could be useful for fade-in splash screens or fancy demos. # Specification A new attribute **-alpha** will be recognized by **wm attributes**. It will take a double value from 0.0 \(completely transparent\) to 1.0 \(opaque\) that signifies the percentage transparency of the toplevel. Thus, **-alpha 0.9** would make the toplevel 90% visible \(10% transparent\). Any value outside [0.0..1.0] will be constrained to the nearest bound. There are some special considerations for this feature. It only works on Windows 2000/XP\+. The code handles the dynamic lookup of the necessary functionality. If you do not have the functionality, then any attempt to set the **-alpha** value will be ignored, and queries to **-alpha** will always return 0 \(opaque\). Layered windows cannot use the CS\_CLASSDC class style, so an alternative class must be made available. This is handled in the implementation transparently, with _UpdateWrapper_ choosing the appropriate class as necessary. Transparent windows will use **TkToplevelNoDC** as their class name \(normal is **TkToplevel**\). Efforts have been made to reduce calls to _UpdateWrapper_. # Reference Implementation See Tk Patch 892194 <http://sf.net/support/tracker.php?aid=892194> The reference patch implements the functionality along with one bug fix to _UpdateWrapper_ - correct setting of the Z order of the window based on the previous wrapper window. While this patch addresses Windows alpha transparency, it is available for other platforms. It is recommended that the same syntax be used across platforms. # Comments Discussion focused around the use of _-alpha_ versus _-transparency_. Some felt that the latter was more familiar to end users. The author refutes this with several points. First, the existing TIP\#166 uses _-alpha_ as well, for the same functionality specific to Tk images \(using the same [0..1] value as well\). Also, the underlying APIs for each platform refer to the alpha level as well. In looking over various documentation, transparency is often a boolean concept, which alpha is the gradual level. This is how it will be used in Tk. # Copyright This document has been placed in the public domain. |
Name change from tip/223.tip to tip/223.md.
|
| < | < | | | | | | | > | | | | | | | | | 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 | # TIP 223: Full-Screen Toplevel Support for Tk Author: Mo DeJong <[email protected]> State: Final Type: Project Vote: Done Created: 21-Sep-2004 Post-History: Tcl-Version: 8.5 ----- # Abstract Tk lacks an optimal method for creating a full-screen **toplevel**. A full-screen toplevel is one that has no borders and a client drawing area that covers the entire screen. On some UNIX systems, one can create a normal toplevel that is a little larger than size of the screen and place the upper left corner of the client drawing area at at \(0,0\). This option is not available under Windows as the position and dimensions of normal windows are constrained to keep them from covering up the start menu and task bar. Under Windows, a zoomed toplevel with the _overrideredirect_ flag set avoids this size restriction and displays with no borders, both desirable properties. Unfortunately, setting the _overrideredirect_ flag also keeps an icon for the toplevel from being displayed in the task bar and in the programs list accessed via Alt-Tab. There are also some UNIX systems that restrict the placement of a normal toplevel window. For example, the default window manager for the KDE desktop restricts size and placement of a normal toplevel in much the same way as Windows. This TIP and its associated patch implement full-screen functionality that also displays an icon in the taskbar and is accessible via Alt-Tab. The implementation adds a new **-fullscreen** option to the **wm attributes** subcommand. # Motivation A Tk developer will at some point need to create a full-screen application. Existing Tk commands under Windows can be used to create a mostly working full-screen application, but the edge cases where it does not work well make the application look unprofessional. The example code<http://wiki.tcl.tk/12506> was created to support a native looking full-screen Windows application using only existing Tk commands. The main problem this example attempts to work around is that a toplevel with the overrideredirect flag set does not show an icon in the Windows taskbar. To address this issue, a second fake window was created and certain events for the fake window are redirected to the full-screen window. This approach works for the most part but there |
︙ | ︙ | |||
65 66 67 68 69 70 71 | The final user visible issue shows up when a full-screen window is first mapped. The window gets mapped in the normal state and is then resized to full-screen instead of being mapped at the size of the screen. These application behaviors do not match native Windows apps and just look unprofessional. As a result, a project was undertaken to create a Tk patch to address these issues. | | | | | | | | < < | > > | | | | | | | | | | | | | > | 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 | The final user visible issue shows up when a full-screen window is first mapped. The window gets mapped in the normal state and is then resized to full-screen instead of being mapped at the size of the screen. These application behaviors do not match native Windows apps and just look unprofessional. As a result, a project was undertaken to create a Tk patch to address these issues. # Proposal The implementation adds a **-fullscreen** attribute that can be set to a boolean value of 0 or 1. Example code to switch a window from normal to full-screen mode is as follows. proc fullscreen_switch { top } { if {[wm attributes $top -fullscreen]} { wm attributes $top -fullscreen 0 } else { wm attributes $top -fullscreen 0 } } An implementation for Windows has been created to support this new **-fullscreen** attribute. The list of changed files is as follows: > _doc/wm.n, tests/winWm.test, tests/wm.test, win/tkWinWm.c_ Tk patch 1032982 has been created to track these modifications. The patch mostly duplicates the way an overrideredirect window is created with some modifications so that the window is the proper size and has an icon in the taskbar. In _UpdateWrapper_ the Win32 _CreateWindowEx_ function is invoked with the WS\_EX\_APPWINDOW flag passed as the _dwExStyle_ argument and \(WS\_POPUP\|WS\_CLIPCHILDREN\|CS\_DBLCLKS\) passed as the _dwStyle_ argument. Example Win32 code to create a standalone example of such a window is also attached and can be found in the file named _full\_screen.c_. The patch also includes additions to the Tk test suite and documentation to cover these modifications. # Alternatives One alternative is to do nothing. The existing pure Tcl implementation works for most cases. Reasons for rejecting this alternative have already been covered in this TIP. An earlier approach that added a new **fullscreen** state available via the **wm state** subcommand was abandoned based on advice from Joe English. After implementing it both ways, both the Tk, and the end user code seemed cleaner using the attributes approach. Assuming the TIP is accepted and a new attribute is added, there is one implementation alternative that might be useful to explore. There may be a way to pass a window manager hint to the Windows OS so that it allows the creation of a normal window that is larger than the height of the screen minus the height of the task bar. That would mean a regular window class could be used instead of a popup class. The only user visible change would be that right clicking on the icon in the taskbar would show a context menu with the Restore, Minimize, Maximise, and Close options. The current patch creates a taskbar icon that always pops the full-screen window to the top on a left or right click. It is not clear that this minor detail is important enough to worry about. # Risks The complexity of Unix and Mac implementation of this TIP is currently not known. # See Also SourceForge patch: 1032982 # Copyright This document has been placed in the public domain. |
Name change from tip/224.tip to tip/224.md.
|
| < | < | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | < > | | | | < > | | < > | | | < < | > > | | | | | | | | | | | | | | | | | | > | 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 | # TIP 224: Add New [array] Subcommands 'incr' and 'value' Author: Peter MacDonald <[email protected]> Author: Robert Seeger <[email protected]> State: Draft Type: Project Vote: Pending Created: 28-Sep-2004 Post-History: Tcl-Version: 8.7 ----- # Abstract The TIP proposes the addition to two new subcommands to the **array** command: **incr** and **value**. The **incr_ subcommand would increment an element in an array. The **value** subcommand would query, reference, and/or initialize an array element. # Rationale [[215]](215.md) proposed modifying the **incr** command to auto-initialize variables which do not exist, rather than throwing an error. After some debate, it was identified that frequency counting in arrays was the primary area of interest. In particular, the excessive use of _if/info exists_ constructs in such code is inefficient, verbose and rather difficult to read. The addition of these two subcommands could substantially reduce the complexity of much Tcl code. # Specification Two new subcommands will be added to **array**, being **incr** and **value**. Both commands take an array name and an elem parameter, but, no string match is performed on elem. ## array incr > **array incr** _var elem_ ?_value_? ?_init_? The **array incr** subcommand would increment _var_\(_elem_\), if it exists, by _value_, otherwise, initializes it to _init_. The default for _value_ is 1, and the default for _init_ is 0. The subcommand will return the new value and will support both integer and double values \(based on the rules for addition in **expr**\). ## array value > **array value** _var elem_ ?_value_? ?_init_? The **array value** would just return the current contents of _var_\(_elem_\) if it exists, or _value_ otherwise. If the _init_ parameter resolves to true \(as determined by _Tcl\_GetBooleanFromObj\(\)_ of course\), the variable is initialized to _value_ if it doesn't already exist. The default for _value_ is the empty string, and the default for _init_ is false. # Reference Implementation Following is a Tcl only implementation of the **incr**/**value** subcommands: proc Array {cmd var elem {amt {}} {init 0}} { # Implement the Array subcmds incr and value on var(elem): # - incr increment a variable by amt or initialize # to init if undefined. # - value return the value if defined, else return amt # initializing if init. upvar $var uvar if {[string match $cmd* incr]} { if {$amt == {}} { set amt 1 } if {[info exists uvar($elem)]} { return [set uvar($elem) [expr {$uvar($elem)+$amt}]] } return [set uvar($elem) $init] } elseif {[string match $cmd* value]} { if {[info exists uvar($elem)]} { return $uvar($elem) } if {$init} { return [set uvar($elem) $amt] } return $amt } else { error "usage: Array incr|value var elem ?amt? ?init?" } } # Discussion * Wangnic notes: > **array value** _var elem_ **"" false** can be written as **array get** _var elem_ > Array get returns name/value pairs. Array value returns just the value. Also if elem has a \* in it, there may be multiple matches. * Hobbs notes: > [[200]](200.md) already rejected _array values_ > A single item is returned from _array value_, not a list, as there is no string match on elem. > The problem domain is not list processing \(which is expected to be relatively expensive\), but rather frequency counting and set matching. * RHSeeger notes: > It would seem more consistant to push for the _incr_ command to include a way to initialize a variable if it doesn't exist \(as per [[215]](215.md) or the discussed options contained therein\), rather than add an incr subcommand to array. > Being a fan or reintroducing the _array values_ TIP \(since the core mailing list indicates it was never fully rejected\), I think _array value_ might be a bit confusing, being only off by the lack of plurality. \(I was one of the people pushing for [[200]](200.md) though, so take that aspect with a grain of salt\) # Copyright This document has been placed in the public domain. |
Name change from tip/225.tip to tip/225.md.
|
| < | < | | | | | | | | > | | | | | | | | < > | | | | < | > | | | | | | < > | < > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | < > | | | | | < > | | < | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | < > | | | | | | | | | | | | | | | | | | | | | < > | | | | | < > | | | < > | < > | | | | > | 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 | # TIP 225: Arithmetic Series with Optimized Space Complexity Author: Salvatore Sanfilippo <[email protected]> Author: Miguel Sofer <[email protected]> State: Draft Type: Project Vote: Pending Created: 25-Oct-2004 Post-History: Tcl-Version: 8.7 ----- # Abstract This TIP proposes to add a new command to generate arithmetic sequences as Tcl lists that may be stored in constant space in many practical situations. The only change from the point of view of the Tcl programmer is the addition of a new command named **range**. # Rationale An idiomatic way to assign successive elements of an arithmetic series to a variable is to use the **for** command. Usually the loop variable is initialized to the first element of the sequence, and incremented at every iteration of a given step using **incr**. The **for** test condition is used to limit the sequence generation to a given element, like in the following example: for {set i 0} {$i < 10} {incr i} { puts $i } The Tcl programming language is at higher level than the C language, where this idiom firstly appeared, so it may be desiderable to be able to generate arithmetic sequences of integer numbers in a more comfortable way. Being the Tcl list a central data structure of the Tcl language, it apperas natural to generate a Tcl list of integers, and possibly use the **foreach** command to loop over every element, so that the above **for** loop can be translated into the following fragment of code: foreach i [range 0 10] { puts $i } The **range** command can be also conveniently used in different contexts. The following code generates a list of squares of 0, 1, 2, 3, ... 9. proc map {varname script mylist} { upvar $varname var set res {} foreach var $mylist { lappend res [uplevel 1 $script] } return $res } puts [map x {expr {$x*$x}} [range 0 10]] # Will output "0 1 4 9 16 25 36 49 64 81" The **range** command can be implemented in a way that makes it possible to internally store the arithmetic sequences genereated in constant space if they are only accessed using **foreach**, **llength** and **lindex** commands \(**lrange** may also be handled in a special way\). When needed, the object will be converted into a List object automatically. From the Tcl programmer point of view this optimization is transparent. # Specification of the Behaviour The **range** command takes three arguments in the complete format, named _start_, _end_ and _step_, and generates a sequence of integers accordingly to the following algorithm in pseudo code: RangeLen(start, end, step) 1. if step = 0 2. then ERROR 3. if start = end 4. then return 0 5. if step > 0 AND start > end 6. then ERROR 7. if setp < 0 AND end > start 8. then ERROR 9. return 1+((ABS(end-start)-1)/ABS(step)) Range(start, end, step) 1. result <- EMPTY LIST 2. len <- RangeLen(start, end, step) 3. for i <- 0 to len - 1 4. result.append(start+(i*step)) 6. return result The _step_ argument can be omitted, and default to the value of 1, so [**range** 0 10 1] is the same as [**range** 0 10]. It's also possible to call the **range** command with a single argument, omitting both the _start_ and _step_ argument that will default respectively to 0 and 1, so that the following three commands will generate the same sequence of integers: range 0 10 1 range 0 10 range 10 The following are examples of outputs. [range 0 10 1] => 0 1 2 3 4 5 6 7 8 9 [range 10 0 -2] => 10 8 6 4 2 [range 10 10] => empty list [range 10 20 -3] => ERROR [range 5] -> 0 1 2 3 4 Infinite series and series resulting in lists bigger than the maximum list length that the Tcl code can handle are detected and reported as an error. _start_, _end_, and _step_ can be anything can fit into a Tcl wide integer. Note that there is a practical justification for the fact that the elements generated never reach the value of the End argument, with the effect of [**range** 0 10 1] generating the sequence 0, 1, 2, ..., 9 and a range with the same value of _start_ and _end_ always generating an emtpy list. This is needed in order to make it comfortable to use **range** and **foreach** instead of **for** loops like in the following example: foreach i [range [llength $mylist]] { foobar [lindex $mylist $i] } Because Tcl indexes are mostly zero-based, and it is often useful to access every element of a sequence given it's length, this appears to be the more sensible behaviour \(this semantic is very similar to the range\(\) function of the Python programming language, where range\(\) is fully used to replace C-like _for_ loops.\) Unfortunately this behaviour is not as comfortable to run the indexes in reverse order: foreach i [range [expr {[llength $mylist]-1}] -1 -1] { foobar [lindex $mylist $i] } But the access from the first to the last element is far more common in programs, and the range command needs to be consistent when the step is negative. An alternative syntax for reverse-indexing is: foreach i [range [llength $mylist]] { foobar [lindex $mylist end-$i] } # Proposed Change The change proposed is to modify the Tcl core in order to handle a new object type called ArithSeries, that is recongnized and handled as a special case by at least the **llength**, **lindex** and **foreach** commands. Syntactically, the ArithSeries object will have the string representation that is exactly that that would be produced by creating a list with the elements that would be iterated over by **foreach** as previously described. This TIP also proposes to add logic into _SetListFromAny_ method of the List type in order to convert an Arithmetic Series object into a List directly without to pass from the string representation. This TIP proposes to add a **range** command to the Tcl core having the semantics specified above, and returning an Arithmetic Series object. Formally, the syntax is: > **range** ?_start_? _end_ ?_step_? The proposed changes are available as a Patch against HEAD that can be found in the SourceForge Tcl patch 1052584 <http://sf.net/tracker/?func=detail&aid=1052584&group_id=10894&atid=310894> # Copyright This document has been placed in the public domain. ---- # Appendix: Reference Pure-Tcl Implementation It may be useful to test the behaviour of the **range** command without having to apply the Patch, so the following is a pure Tcl implementation that should be exactly equivalent in the semantic to the specification in this TIP, but of course not able to store ranges in O\(1\) space. # RangeLen(start, end, step) # 1. if step = 0 # 2. then ERROR # 3. if start = end # 4. then return 0 # 5. if step > 0 AND start > end # 6. then ERROR # 7. if setp < 0 AND end > start # 8. then ERROR # 9. return 1+((ABS(end-start)-1)/ABS(step)) proc rangeLen {start end step} { if {$step == 0} {return -1} if {$start == $end} {return 0} if {$step > 0 && $start > $end} {return -1} if {$step < 0 && $end > $start} {return -1} expr {1+((abs($end-$start)-1)/abs($step))} } # Range(start, end, step) # 1. result <- EMPTY LIST # 2. len <- RangeLen(start, end, step) # 3. for i <- 0 to len - 1 # 4. result.append(start+(i*step)) # 6. return result proc range args { # Check arity set l [llength $args] if {$l == 1} { set start 0 set step 1 set end [lindex $args 0] } elseif {$l == 2} { set step 1 foreach {start end} $args break } elseif {$l == 3} { foreach {start end step} $args break } else { error {wrong # of args: should be "range ?start? end ?step?"} } # Generate the range set rlen [rangeLen $start $end $step] if {$rlen == -1} { error {invalid (infinite?) range specified} } set result {} for {set i 0} {$i < $rlen} {incr i} { lappend result [expr {$start+($i*$step)}] } return $result } ---- # Appendix: Discussion Does the TIP include a C-level api to ranges, or are they transparent also in C - in the sense that they are addressable with any of the list-oriented functions of the Tcl api? What if any changes and caveats are necessary in the documentation of Tcl's C api? _Miguel_ Ranges are transparent to C level too, in the proposed patch, because the logic is put inside the commands, so directly in the code implementing lindex, foreach, ... In all the other cases, when a SetListFromAny\(\) call occurs the range is converted into a normal Tcl list object. _Salvatore_ |
Name change from tip/226.tip to tip/226.md.
|
| < | < | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 226: Interface to Save and Restore Interpreter State Author: Don Porter <[email protected]> State: Final Type: Project Vote: Done Created: 30-Oct-2004 Post-History: Keywords: Tcl Tcl-Version: 8.5 ----- # Abstract This TIP proposes new public C routines to allow the dynamic state of an interp, including the return options, and error logging in progress as well as the interp result, to be saved and later restored. # Background The Tcl C library has long recognized the need for some routines to be able to make use of a _Tcl\_Interp_ without leaving any lasting footprints behind, and without interfering with whatever operations that _Tcl\_Interp_ might be in the midst of performing. The longstanding routines used to address this need have been _Tcl\_SaveResult_, _Tcl\_RestoreResult_, and _Tcl\_DiscardResult_. These existing routines also have known limitations. The documentation warns that they should not be used when an error is in progress, because they are not able to preserve the extra error information in the _Tcl\_Interp_, only the result. The existing routines are also showing their age. Because they focus on the result of the _Tcl\_Interp_, and because they date from at least the Tcl 7 days, they spend an inordinate amount of effort tending to the needs of the long-deprecated _interp->result_ field. Also, they make use of the transparent definition of a public struct, _Tcl\_SavedResult_, and expect the caller to allocate such structs itself, a practice now frowned upon, and replaced with the use of opaque structs. The Itcl extension has long worked around the limitations of _Tcl\_SaveResult_, etc. by defining its own set of routines that more completely save and restore the state of a _Tcl\_Interp_. These routines are _Itcl\_SaveInterpState_, _Itcl\_RestoreInterpState_, and _Itcl\_DiscardInterpState_. These routines are able to handle the case of an error in progress, and have an interface making use of an opaque struct, _Itcl\_InterpState_. In order to create these routines, however, the Itcl extension makes direct access to some of the private fields of Tcl's _Interp_ struct. In Tcl 8.5, the proposal of [[90]](90.md) have already extended further the values that make up the state of a _Tcl\_Interp_, including a return level, and a dictionary of return options. Also, some of the internal fields of the _Interp_ struct have been reworked, so that the Itcl routines no longer function without modification. It it time for Tcl to provide public interfaces that perform the functions of the _Itcl\_\*InterpState_ routines, and in fact, Tcl should provide exactly those routines. # Proposal Three new routines will be added to Tcl's public stub table: > Tcl\_InterpState **Tcl\_SaveInterpState**\(Tcl\_Interp \*_interp_, int _status_\) > int **Tcl\_RestoreInterpState**\(Tcl\_Interp \*_interp_, Tcl\_InterpState _state_\) > void **Tcl\_DiscardInterpState**\(Tcl\_InterpState _state_\) Also an opaque struct will be declared in **tcl.h**: > typedef struct Tcl\_InterpState\_ \***Tcl\_InterpState**; These routines are to have the same function as their existing Itcl counterparts. These declarations and routines already exist in the HEAD of Tcl's development sources, but as private routines. The Tcl source code itself has already had an upgrade to replace all uses of the old _Tcl\_SaveResult_ calls with these new routines. This TIP merely proposes making these routines available as part of the public interface. # Compatibility Strictly speaking, there are no compatibility issues, since these are new additions to the public interface. Callers of the _Tcl\_SaveResult_ family of routines should be encouraged to update to use the new routines, as they perform the same function and more. The _Tcl\_SaveResult_ family of routines should be kept in the public interface at least through the Tcl 8 series of releases, though. Consideration of their removal for Tcl 9 is left for another proposal. Itcl will have compatibility issues with Tcl 8.5 because of the changes to the internal fields of Tcl's _Interp_ struct. Itcl should make use of these new routines as the implementation of its corresponding routines whenever compiling against a Tcl 8.5 set of headers. When doing that, of course, version 8.5 of the Tcl stubs table will need to be required. # Reference Implementation See Tcl Patch 1060579. # Comments Please make any comments here. # Copyright This document has been placed in the public domain. |
Name change from tip/227.tip to tip/227.md.
|
| < | < | | | | | | | | > | | | | | | | | | | | | | | | | | | < > | | | | < | | > | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 227: Interface to Get and Set the Return Options of an Interpreter Author: Don Porter <[email protected]> State: Final Type: Project Vote: Done Created: 30-Oct-2004 Post-History: Keywords: Tcl Tcl-Version: 8.5 ----- # Abstract This TIP proposes new public C routines to allow the same access to interpreter return options [[90]](90.md) as are provided at the script level by the **catch** and **return** commands. # Background In Tcl 8.5, the **return** command has aready been extended to accept all option value pairs passed to it as arguments, to permit extensions to augment any custom return code values with whatever additional data values are appropriate. The **errorInfo** and **errorCode** values associated with the **TCL\_ERROR** return code are already converted to this mechanism. The ability to set custom return options in the interp has been limited to the script level though. For extension commands implemented entirely in C, it is inconvenient and somewhat unreliable to perform a _Tcl\_Eval\("return ..."\)_ to be able to access this capability. Likewise, the **catch** command is able to capture the current set of return options in the interp, but doing so requires both a script level command, and use of a variable. Extension commands implemented in C are better served with a direct interface to fetch the dictionary value. # Proposal Two new routines will be added to Tcl's public stub table: > int **Tcl\_SetReturnOptions**\(Tcl\_Interp \*_interp_, Tcl\_Obj \*_options_\) > Tcl\_Obj \***Tcl\_GetReturnOptions**\(Tcl\_Interp \*_interp_, int _result_\) These routines already exist in the HEAD of Tcl's development sources, but as private routines. The Tcl source code itself already makes calls to these routines where appropriate, and their functioning is tested by the test suite. This TIP merely proposes making these routines available as part of the public interface. The _Tcl\_SetReturnOptions_ routine is essentially equivalent to the **return -options** command. The _int_ value returned is the return code that the **return** command would return given the same options. In fact, a valid implementation for the **return** command would be: int Tcl_ReturnObjCmd(ClientData cd, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { int explicitResult = (0 == (objc %2)); int numOptions = objc - 1 - explicitResult; if (explicitResult) Tcl_SetObjResult(interp, objv[objc-1]); return Tcl_SetReturnOptions(interp, Tcl_NewListObj(numOptions, objv+1)); } Note that _Tcl\_SetReturnOptions_ is like _Tcl\_SetObjResult_ and _Tcl\_SetVar2Ex_ in that you can pass it a newly created Tcl\_Obj confident that it will be freed later. No refCount manipulation is required. The _Tcl\_GetReturnOptions_ routine is used by **catch** to fetch the value to be stored in the _optionsVarName_ variable, if any. The _result_ argument should be whatever return code was returned by the script evaluation, or other _interp_ activity whose return options you wish to retrieve. The _\(Tcl\_Obj \*\)_ returned by _Tcl\_GetReturnOptions_ points to a newly created, unshared **Tcl\_Obj**. It can be written to as returned; no need to implement copy-on-write checks. In particular, new key value pairs can be added to the dictionary, or existing ones changed or removed. As noted above, such a value is also suitable for passing right back to _Tcl\_SetReturnOptions_. # Compatibility Some extensions provide commands that offer the ability to evaluate a Tcl script in some other context, and return the complete result of that evaluation. For example, the **Thread** package provides the **thread::send** command that evaluates a script in another interp in a different thread. The **thread::send** command ultimately has a return code and a result that matches those produced by the script evaluation in the other thread. Furthermore, the **::errorInfo** and **::errorCode** variables are set according to the script evaluation outcome in the other thread as well. Extensions that accomplish such passing of full evaluation results achieve it now with copies of all portions of the full evaluation results: the return code, the interp result, and when appropriate, the values of **::errorInfo** and **::errorCode**. Such mechanisms will continue to work unchanged in Tcl 8.5. However, they will no longer represent the _complete_ evaluation results of the script. In order to continue to communicate back the full outcome of script evaluation, these extensions will want to call _Tcl\_GetReturnOptions_ after the script completes, transport that value back, and call _Tcl\_SetReturnOptions_ in the original interp. Note that use of these routines will automatically take care of **::errorInfo** and **::errorCode**, so the complete outcome of script evaluation will be able to be communicated by the return code, the interp result, and the dictionary of return options. Because the return options dictionary is itself extensible, this interface will not need to change again. # Reference Implementation See Tcl Patch 1060579. # Comments Please make any comments here. # Copyright This document has been placed in the public domain. |
Name change from tip/228.tip to tip/228.md.
|
| < | < | | | | | | | | | > | | | | | | | | 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 | # TIP 228: Tcl Filesystem Reflection API Author: Andreas Kupries <[email protected]> Author: Andreas Kupries <[email protected]> Author: Vince Darley <[email protected]> State: Draft Type: Project Vote: Pending Created: 02-Nov-2004 Post-History: Tcl-Version: 8.7 ----- # Abstract This document describes an API which reflects the Filesystem Driver API of the core Virtual Filesystem Layer up into the Tcl level, for the implementation of filesystems in Tcl. It is an independent companion to [[219]](219.md) \('Tcl Channel Reflection API'\) and [[230]](230.md) \('Tcl Channel Transformation Reflection API'\). As the latter TIPs bring the ability of writing channel drivers and transformations in Tcl itself into the core so this TIP provides the facilities for the implementation of filesystems in Tcl. This document specifies version _1_ of the filesystem reflection API. # Motivation / Rationale The purpose of this and the other reflection TIPs is to provide all the facilities required for the creation and usage of wrapped files \(= virtual filesystems attached to executables and binary libraries\) within the core. While it is possible to implement and place all the proposed reflectivity in separate and external packages, this however means that the core itself cannot make use of wrapping technology and virtual filesystems to encapsulate and attach its own data and library files to itself. Something which is desirable as it can make the |
︙ | ︙ | |||
49 50 51 52 53 54 55 | we managed to envision. Another use for reflected filesystems is as a helper for testing the generic filesystem layer of Tcl, by creating filesystems which forcibly return errors, bogus data, and the like. An implementation of this TIP exists already as a package, | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 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 | we managed to envision. Another use for reflected filesystems is as a helper for testing the generic filesystem layer of Tcl, by creating filesystems which forcibly return errors, bogus data, and the like. An implementation of this TIP exists already as a package, **TclVfs**. This TIP asks to make that mechanism publicly available to script and package authors, with a bit of cleanup regarding the Tcl level API. # Specification of Tcl-Level API The Tcl level API consists of a single new command, **filesystem**, and one change to the existing command **file**. The new command is an ensemble command providing five subcommands. These subcommands are **mount**, **unmount**, **info**, **posixerror**, and **internalerror**. \(Note that this TIP does not introduce a new C API, but rather exposes an existing C API to Tcl scripts.\) ## The mount Subcommand > **filesystem mount** ?_-volume_? _path cmdprefix_ This subcommand creates a new filesystem using the command prefix _cmdprefix_ as its handler. The API this handler has to provide is specified below, in the section "Command Handler API". The new filesystem is immediately mounted at _path_. After completion of the call any access to a subdirectory of _path_ will be handled by that filesystem, through its handler. The filesystem is represented here by the command prefix which will be executed whenever an operation on a file or directory within path has to be performed. If the option **-volume** is specified then the new mount point is also registered with Tcl as a new volume and will therefore from then on appear in the output of the command **file volumes**. This is useful \(and actually required for reasonable operation\) when mounting paths like **ftp://**. It should not be used for paths mounted inside the native filesystem. The new filesystem will be immediately accessible in _all_ interpreters executed by the current process. The command returns the empty string as its result. Returning a handle or token is not required despite the fact that the handler command can be used in more than one mount operation. The different instances can be clearly distinguished through the _root_ argument given to each called method. This _root_ is identical to the _path_ specified here. In other words, the chosen _path_ \(= mount point\) is the handle as well. We have chosen to use _early binding_ of the handler command. See the section "Early versus late binding of the handler command" for more detailed explanations. **Important note**: The handler command for the filesystem resides in the interpreter performing the mount operation. This interpreter is the **filesystem interpreter** mentioned in the section "Interaction with threads and other interpreters". ## The unmount Subcommand > **filesystem unmount** _path_ This methods unmounts the reflected filesystem which was mounted at _path_. An error is thrown if no reflected filesystem was mounted at that location. After the completion of the operation the filesystem which was mounted at that location is not visible anymore, and any previous filesystem accessible through this path becomes accessible again. The command returns the empty string as its result. ## The info Subcommand > **filesystem info** ?_path_? This method will return a list of all filesystems mounted in all interpreters, if it was called without arguments. When called with a _path_ the reflected filesystem responsible for that path is examined and the command prefix used to handle all filesystem operations is returned. An error is thrown if no reflected filesystem is mounted for that path. There is currently no facility to determine the **filesystem interpreter** \(nor its thread\). ## The posixerror Subcommand > **filesystem posixerror** _error_ This command can be called by a handler command during the execution of a filesystem operation to signal the POSIX error code of a failure. This also aborts execution immediately, behaving like **return -code -1**. The argument _error_ is either the integer number of the POSIX error to signal, or its symbolic name, like "EEXIST", "ENOENT", etc. ## The internalerror Subcommand > **filesystem internalerror** _cmdprefix_ This method registers the provided command prefix as the command to call when the core has to report internal errors thrown by a handler command for a reflected filesystem. If no such command is registered, then internal errors will stay invisible, as the core currently does not provide a way for reporting them through the regular VFS layer. We have chosen to use _early binding_ of the handler command. See the section "Early versus late binding of the handler command" for more detailed explanations. ## Modifications to the file Command The existing command **file_ is modified. Its method **normalize** is extended to recognize a new switch, _-full_. When this switch is specified the method performs a normal expansion of _path_ first , followed by an expansion of any links in the last element of _path_. It returns the result of the expansion as its own result. The new signature of the method is * **file normalize** ?_-full_? _path_ # Command Handler API The Tcl-level handler command for a reflected filesystem has to support the following subcommands, as listed below. Note that the term _ensemble_ is used to generically describe all command \(prefixes\) which are able to process subcommands. This TIP is _not_ tied to the recently introduced 'namespace ensemble's. There are three arguments whose meaning does not change across the methods. They are explained now, and left out of the specifications of the various methods. root: This is always the path the filesystem is mounted at, i.e. the handle of the filesystem. In other words, it is the part of the absolute path we are operating upon which is 'outside' of the control of this filesystem. relative: This is always the full path to the file or directory the operation has to work on, relative to _root_ \(s.a.\). In other words, it is the part of the absolute path we are operating upon which is 'inside' of the control of the reflected filesystem. actualpath: This is the exact path which was given to the file command which caused the invocation of the handler command. This path can be absolute or relative. If it is absolute then _actualpath_ is identical to "root/relative". Otherwise it can be a sub- or super-path of _relative_, depending on the current working directory. And finally the list of methods and their detailed specification. ## The initialize Method > _handler_ **initalize** _root_ This method is called first, and then never again \(for the given _root_\). Its responsibility is to initialize all parts of the filesystem at the Tcl level. The return value of the method has to be a list containing two elements, the version of the reflection API, and a list containing the names of all methods which are supported by this handler. Any error thrown by the method will prevent the creation of the filesystem and aborts the mount operation which caused the call. The thrown error will appear as error thrown by **filesystem mount**. The current version is _1_. ## The finalize Method > _handler_ **finalize** _root_ The method is called when the filesystem was **unmount**ed, and is the last call a handler can receive for a specific _root_. This happens just before the destruction of the C level data structures. Still, the command handler must not access the filesystem anymore in no way. It is now his responsibility to clean up any internal resources it allocated to this filesystem. The return value of the method is ignored. Any error thrown by the method is returned as the error of the **unmount** command. ## The access Method * _handler_ **access** _root relative actualpath mode_ This method is called to determine the "access" permissions for the file \(_relative_\). It has to either return successfully, or signal a POSIX error \(See **filesystem posixerror**. The latter means that the permissions asked for via _mode_ are not compatible with the file. Any result returned by the method is ignored. Regular errors thrown by the method are reported through the registered handler for internal errors, if there is any. They are ignored if no such handler is present. The argument _mode_ is a list containing any of the strings **read**, **write**, and **exe**, the permissions the file has to have for the request to succeed. * **write** contained in _mode_ implies "writable". * **read** contained in _mode_ implies "readable". * **exe** contained in _mode_ implies "executable". ## The createdirectory Method > _handler_ **createdirectory** _root relative actualpath_ This method has to create a directory with the given name \(_relative_\). The command can assume that _relative_ does not exist yet, but the directory _relative_ is in does. The C level of the reflection takes care of this. Any result returned by the method is ignored. Errors thrown by the method are reported through the registered handler for internal errors, if there is any. They are ignored if no such handler is present. ## The deletefile Method > _handler_ **deletefile** _root relative actualpath_ This method has to delete the file _relative_. Any result returned by the method is ignored. Errors thrown by the method are reported through the registered handler for internal errors, if there is any. They are ignored if no such handler is present. ## The fileattributes Method > _handler_ **fileattributes** _root relative actualpath_ ?_index_? ?_value_? The command has to return a list containing the names of all acceptable attributes, if neither _index_ nor _value_ were specified. The command has to return the value of the _index**th attribute if the _index_ is specified, but not the _value_. The attributes are counted in the same order as their names appear in the list returned by a call where neither _index_ nor _value_ were specified. The first attribute is has the index 0. The command has to set the value of the _index**th attribute to _value_ if both _index_ and _value_ were specified for the call. Any result returned by the method is ignored for this case. Errors thrown by the method are reported through the registered handler for internal errors, if there is any. They are ignored if no such handler is present. ## The matchindirectory Method > _handler_ **matchindirectory** _root relative actualpath pattern types perm mac_ This method has to return the list of files or directories in the path _relative_ which match the glob _pattern_, are compatible with the specified list of _types_, have the given _perm_issions and _mac_ creator/type data. The specified path is always the name of an existing directory. **Note**: As the core VFS layer generates requests for directory-only matches from the filesystems involved when performing any type of recursive globbing this subcommand absolutely has to handle such \(and file-only\) requests correctly or bad things \(TM\) will happen. Errors thrown by the method are reported through the registered handler for internal errors, if there is any. They are ignored if no such handler is present. _types_ is a list of strings, interpreted as set. The strings are the names of the types of files the caller is looking for. Allowed strings are: **files**, and **dirs**. The command has to return all files which match **at least one** of the types. If _types_ is empty then all types are valid. _perm_ is a list of permission strings \(i.e. a set\), i.e. **read**, **write**, and **exe**. The command has to return all files which have **at least all** the given permissions. If _perm_ is empty then no permissions are required. _mac_ is a list containing 2 strings, for Macintosh creator and type. If _mac_ is empty then the data is irrelevant. ## The open Method > _handler_ **open** _root relative actualpath mode permissions_ This command has to return a list describing the successfully opened file _relative_, or throw an error describing how the operation failed. The thrown error will appear as error thrown by the _open_ command which caused the invocation of the handler. The list returned upon success contains at least one and at most two elements. The first element is obligatory and is always the handle of the channel which was created to allow access to the contents of the file. If the second element is present it will be interpreted as a callback, i.e. a command prefix. This prefix will always be executed as is, i.e. without additional arguments. Any required arguments have to be returned as part of the result of the call to **open**. This callback is fully specified in section "The channel close callback". The argument _mode_ specifies if the file is opened for read, write, both, appending, etc. Its value is a string in the set **r**, **w**, **a**, **w\+**, or **a\+**. The argument _permissions_ determines the native mode the opened file is created with. This is relevant only if the _mode_ actually requests the creation of a non-existing file, i.e. is not **r**. **Note**: it is possible to return a channel implemented through reflection here. See also section "The channel close callback" for more. ## The removedirectory Method > _handler_ **removedirectory** _root relative actualpath recursive_ This method has to delete the given directory. The argument _recursive_ is a boolean value. The method has to signal the POSIX error "EEXIST" if _recursive_ is **false** and the directory is not empty. Otherwise it has to attempt to recursively delete the directory and its contents. Any result returned by the method is ignored. Regular errors thrown by the method are reported through the registered handler for internal errors, if there is any. They are ignored if no such handler is present. ## The stat Method > _handler_ **stat** _root relative actualpath_ This method has to return a dictionary containing the stat structure for the file _relative_. Errors thrown by the method are reported through the registered handler for internal errors, if there is any. They are ignored if no such handler is present. The following keys and their values have to be provided by the filesystem: dev: A long integer number, the device number of the path stat was called for. This number is optional and always overwritten by the C level of the filesystem reflection. ino: A long integer number, the inode number of the path stat was called for. mode: An integer number, the encoded access mode of the path. It is this mode which is checked by the method **access**. nlink: A long integer number, the number of hard links to the specified path. uid: A long integer number, the id of the user owning the virtual path. gid: A long integer number, the id of the user group the virtual path belongs to. size: A long integer number, the true size of the virtual path, in bytes. atime: A long integer number, the time of the latest access to the path, in seconds since the epoch. Convertible into a readable date/time by the command **clock format**. mtime: A long integer number, the time of the latest modification of the path, in seconds since the epoch. Convertible into a readable date/time by the command **clock format**. ctime: A long integer number, the time of the path was created, in seconds since the epoch. Convertible into a readable date/time by the command **clock format**. type: A string, either **directory**, or **file**, describing the type of the given path. Notes: The stat data is highly Unix-centric, especially device node, inode, and the various ids for file ownership. While the latter are not that important both device and inode number can be crucial to higher-level algorithms. An example would be a |
︙ | ︙ | |||
464 465 466 467 468 469 470 | other with regard to device ids this information will be generated by the common C level of the filesystem reflection. The inode numbers however have to be assigned by the filesystem itself. It is possible to make a higher-level algorithm depending on | | | | | | | | | | | | | | | | | | | | | 463 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 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 | other with regard to device ids this information will be generated by the common C level of the filesystem reflection. The inode numbers however have to be assigned by the filesystem itself. It is possible to make a higher-level algorithm depending on device/inode data aware of the problem with virtual filesystems \(and has actually been done, see the Tcllib directory walker\), this however is a kludgey solution and should be avoided. ## The utime Method > _handler_ **utime** _root relative actualpath atime ctime mtime_ This method has to set the access and modification times of the file _relative_. The access time is set to _atime_, creation time to _ctime_, and the modification time is set to _mtime_. The arguments are positive integer numbers, the number of seconds since the epoch. Any result returned by the method is ignored. Errors thrown by the method are reported through the registered handler for internal errors, if there is any. They are ignored if no such handler is present. ## The copyfile Method > _handler_ **copyfile** _root relative\_src actualpath\_src relative\_dst actualpath\_dst_ This method is optional. It has to create a copy of a file in the filesystem under a different name, in the _same_ filesystem. This method is not for copying of files between different filesystems and won't be called for such. Any result returned by the method is ignored. Errors thrown by the method are reported through the registered handler for internal errors, if there is any. They are ignored if no such handler is present. If this method is not supported the core filesystem layer will fall back to a Tcl & channel based method of copying the file. The same fallback will happen if the method is available, but signals the POSIX error "EXDEV". ## The copydir Method > _handler_ **copydir** _root relative\_src actualpath\_src relative\_dst actualpath\_dst_ This method is optional. It has to create a recursive copy of a directory in the filesystem under a different name, in the **same** filesystem. This method is not for copying of directories between different filesystems and won't be called for such. Any result returned by the method is ignored. Errors thrown by the method are reported through the registered handler for internal errors, if there is any. They are ignored if no such handler is present. If this method is not supported the core filesystem layer will fall back to a Tcl based method of copying the directory file by file.. The same fallback will happen if the method is available, but signals the POSIX error "EXDEV". ## The rename Method > _handler_ **rename** _root relative\_src actualpath\_src relative\_dst actualpath\_dst_ This method is optional. It has to rename a file in the filesystem, giving it a different name in the **same** filesystem. This method is not for the renaming of files between different filesystems and won't be called for such. Any result returned by the method is ignored. Errors thrown by the method are reported through the registered handler for internal errors, if there is any. They are ignored if no such handler is present. If this method is not supported the core filesystem layer will fall back to a Tcl & channel based method of renaming the file. The same fallback will happen if the method is available, but signals the POSIX error "EXDEV". # Interaction with Threads and Other Interpreters. Virtual filesystems in Tcl are process global structures. In other words, they are seen and accessible by all interpreters, and all threads in the current process. For filesystems implemented completely at the C-level this is not that big a problem. However a filesystem implemented based on the reflection here will |
︙ | ︙ | |||
575 576 577 578 579 580 581 | executing the driver functionality in the filesystem interpreter instead. In the case of requests coming from a different thread the C level part of the reflection will post specialized events to the filesystem thread, essentially forwarding the invocations of the driver. When a thread or interpreter is deleted all filesystems mounted with | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 | executing the driver functionality in the filesystem interpreter instead. In the case of requests coming from a different thread the C level part of the reflection will post specialized events to the filesystem thread, essentially forwarding the invocations of the driver. When a thread or interpreter is deleted all filesystems mounted with the **filesystem mount** command using this thread/interpreter as their computing base will be automatically unmounted and deleted as well. This pulls the rug out under the other thread\(s\) and/or interpreter\(s\), this however cannot be avoided. Future accesses will either fail because the virtual files are now missing, or will access different files provided by a different filesystem now owning the path. # Interaction with Safe Interpreters The command **filesystem** is unsafe and safe interpreters are not allowed to use it. The reason behind this restriction: The ability of mounting filesystems gives a safe interpreter the ability to inject code into a trusted interpreter. The mechanism is as follows: * An application using a trusted master interpreter and safe slaves for plugins reads and evaluates a file **foo** directly in the trusted interpreter. * A malicious plugin loaded into one of the safe slaves knows about this file **foo**, and its actual location. It mounts a virtual filesystem using a driver which is part of its own code, over the directory **foo** is in. * When the trusted interpreter reads **foo**, it does not go to the native filesystem anymore, but the mounted filesystem. In other words the driver in the slave provides the contents, the code which is executed in the trusted environment. From here on the slave can do anything it wishes in the trusted environment. * Access to any other file in the directory can be passed through unchanged to the filesystem originally owning the path. # The Channel Close Callback The channel close callback is an optional callback which can be set up by the Tcl layer when a file is opened. This is done in the **open** method, by returning a 2-element list. The first element is the channel handle as usual and the second element the command prefix of the callback. The command prefix is early-bound, i.e. the command will be resolved when the callback is set up. The resolution happens in the current context, and thus can be anywhere in the application. Because of this it is strongly recommended to use a fully-qualified command name in the callback. The callback is executed in the current context of the operation which caused the channel to close. It is executed just before the channel is closed **by the generic filesystem layer**. The callback itself **must not** call **close**. It will always be executed as is, i.e. without additional arguments. Any required arguments have to be made part of the prefix when it is set up. The channel is still live enough at the time of the call to allow **seek** and **read** operations. In addition all available data will have been flushed into it already. This means, for example, that the callback can seek to the beginning of the said channel, read its contents and then store the gathered data elsewhere. In other words, this callback is not only crucial to the cleanup of any resources associated with an opened file, but also for the ability to implement a filesystem which can be written to. This does assume that the filesystem does not use a reflected channel to access the contents of the virtual file. If a reflected channel is used however, the close callback is not required, as the _finalize_ method of the channel can be used for the same purpose. Under normal circumstances return code and any errors thrown by the callback itself are ignored. In that case errors have to be signaled asynchronously, for example by calling _bgerror_. Any result returned by the callback is ignored. Errors thrown by the callback are reported through the registered handler for internal errors, if there is any. They are ignored if no such handler is present. **Note** that it is possible that the channel we are working with here is implemented through reflection. The order in which the various callbacks are called during closing is this: * The channel for the file is closed via _close_ by the VFS. * The channel close callback has been set up as a regular close handler, and is called now. * The close function of the channel driver is called, reflected into the Tcl level and cleans it up. * The close operation completes. The important point here is that the channel close callback set up by the filesystem is definitely called before the reflected channel cleans up its Tcl layer, so the assertion above about the channel being live enough to be read and saved from the filesystem Tcl layer holds even if both filesystem and channel are reflected. It also holds if reflected transformations are involved. # Early versus Late Binding of the Handler Command We have two principal methods for using the handler command. These are called early and late binding. Early binding means that the command implementation to use is determined at the time of the creation of the channel, i.e. when _chan create_ is executed, before any methods are called. Afterward it cannot change. The result of the command resolution is stored internally and used until the channel is destroyed. Renaming the handler command has no effect. In other words, the system will automatically call the command under the new name. The destruction of the handler command is intercepted and causes the channel to close as well. Late binding means that the handler command is stored internally essentially as a string, and this string is mapped to the implementation to use for each and every call to a method of the handler. Renaming the command, or destroying it means that the next call of a handler method will fail, causing the higher level channel command to fail as well. Depending on the method the error message may not be able to explain the reason of that failure. Another problem with this approach is that the context for the resolution of the command name has to be specified explicitly to avoid problems with relative names. Early binding resolves once, in the context of the _chan create_. Late binding performs resolution anywhere where channel commands like **puts**, **gets**, etc. are called, i.e. in a random context. To prevent problems with different commands of the same name in several namespaces it becomes necessary to force the usage of a specific fixed context for the resolution. Note that moving a different command into place after renaming the original handler allows the Tcl level to change the implementation dynamically at runtime. This however is not really an advantage over early binding as the early bound command can be written such that it delegates to the actual implementation, and that can then be changed dynamically as well. # Limitations For now this section documents the existing limitations of the reflection. The code of the package **TclVfs** has only a few limitations. * One subtlety one has to be aware of is that mixing case-\(in\)sensitive filesystems and application code may yield unexpected results. > For example mounting a case-sensitive virtual filesystem into a case-insensitive system \(like the standard Windows or MacOS filesystems\) and then using this with code relying on case-insensitivity problems will appear when accessing the virtual filesystem. > Note that application code relying on case-insensitivity will not under Unix either, i.e. is inherently non-portable, and should be fixed. * The C-API's for the methods **link** and **lstat** are currently not exposed to the Tcl level. This may be done in the future to allow virtual filesystems implemented in Tcl to support the reading and writing of links. > **Note** - Exposure of links may require path normalization and native path generation, something the TclVfs implementation does not support. This limitation regarding any type of link, hard or or soft, is quite deeply entrenched in the TclVfs code. * The public C-API filesystem function **Tcl\_FSUtime** is Unix-centric, its main data argument is a _struct utimbuf \*_. This structure contains only a single value for both _atime_ and _ctime_. The method **utime** of the handler command was nevertheless defined to take separate values for access and creation times, in case that this changes in the future. * The Tcl core VFS layer was written very near to regular filesystems and has no way to transport regular Tcl error messages through it. This is the reason for the introduction of the internal error callback. This problem cannot be fixed within the 8.5 line as it requires more extensive changes to the public API. Note that when such changes are done the reflection API has to change as well, as it then allows the direct passing of errors. At that point the C layer of the reflection will have to support both this and the new version of the API. # Examples of Filesystems The filesystems provided by **TclVfs** are all examples. * webdav * ftp sites * http sites * zip archive * tar archive * metakit database * namespace/procedures as filesystem * widget fs Some examples can be found on the Tcler's Wiki, see pages referring to <http://wiki.tcl.tk/11851> * Encryption * Compression * Jails * Quotas # Reference Implementation The package **TclVfs**<http://sourceforge.net/projects/tclvfs/> can serve as the basis for a reference implementation. The final reference implementation will be provided at SourceForge, as an entry in the Tcl Patch Tracker. The exact url will be added here when it becomes available. # Comments Comments on <http://mini.net/tcl/12328> suggest it might be a good idea to modify the 'file attributes' callback to make it more efficient for vfs writers, especially across a network and when vfs's are stacked. Currently one needs to make multiple calls to accomplish anything. [ Add comments on the document here ] # Copyright This document has been placed in the public domain. |
Name change from tip/229.tip to tip/229.md.
|
| < | | | | | | < | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | < < | > > | | | | < > | | | < < | > > | | | > | 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 | # TIP 229: Scripted Control of Name Resolution in Namespaces State: Final Type: Project Tcl-Version: 8.5 Vote: Done Post-History: Author: Donal K. Fellows <[email protected]> Created: 03-Nov-2004 ----- # Abstract This TIP proposes extensions to the **namespace** command to allow scripts to control how individual namespaces map names to commands. # Rationale Tcl has, for historic reasons, attracted many different styles of object system, and a favoured mechanism for implementing objects is on top of namespaces \(which were introduced in Tcl 8.0 based on work done previously in [incr Tcl]\). However, a common problem that these OO systems face is the inability to make namespaces efficiently map names of entities within classes etc. into the object instances. This TIP provides a simple mechanism for doing this. No mechanism is provided for affecting the resolving of variable names. Best practice is to ensure that variables not present in the current namespace are imported explicitly through the **upvar** or **variable** commands \(depending on context\) and the fact that there is any possibility of non-local variable name resolution has been behind a number of bugs in the core \(e.g. Bug \#981733\). # Proposed Change ## Namespace Path Subcommand The **namespace** command will gain a new subcommand, **path**, with the following syntax: > **namespace path** ?_list_? This command sets and queries the current namespace's command name resolution path. If _list_ is present, **namespace path** sets the path to the list of namespaces named in the list and returns the empty string; all the namespaces must exist or an error is thrown. If no _list_ argument is provided, **namespace path** doesn't change anything and returns the current path. ## Updates to Other Commands The **info commands** command shall be updated so that, when no namespace is present in its pattern part, it shall return all \(matching\) commands that are visible without namespace qualifiers at this point. The **info procs** command will not be so modified. ## Name Path Behaviour Only names without a leading namespace separator in them are resolved using the namespace's path. When resolving command names, resolving relative to the current namespace is always preferred \(unless a resolver is installed, of course\), and resolution relative to the global namespace is always done after resolving relative to everything in the path \(unless the global namespace is explicitly in the path, when it happens earlier\). This means that the old behaviour is exactly what you get when the path is empty, and also ensures that virtually all scripts continue to work when a path is set; if it was possible to remove the global namespace from the actual path \(as opposed to the settable part\), virtually all scripts would break. If an extension installs a custom name resolver, that completely overrides the command name resolution path mechanism \(to maximize backward-compatability; it is not anticipated that much code will try to mix the two mechanisms in a namespace\). Note that each namespace's path is isolated from the path of every other namespace, including the parent namespace. Systems using the **namespace path** mechanism as part of an implementation of inheritance will want to set up the path for each object namespace explicitly \(this value can be statically precomputed on a per-class basis\); indeed, where multiple inheritance is involved it will probably be more efficient to compute the path than let Tcl guess. The path is parsed completely at the time the **namespace path** command is run, and the resulting list of namespaces is used directly. If a namespace on some namespaces' path is deleted, it is immediately excised from the path of every namespace that refers to it. ## Examples The following script returns "::foo": namespace eval ::foo { proc boo {} {namespace current} namespace eval bar { namespace path ::foo boo } } The following script return "::foo::bar": namespace eval ::foo { proc boo {} {namespace current} namespace eval bar { proc boo {} {namespace current} } namesspace eval spong { namespace path ::foo bar::boo } } # Implementation A patch is available<http://sf.net/tracker/?func=detail&aid=1159942&group_id=10894&atid=310894> . # Copyright This document has been placed in the public domain. |
Name change from tip/23.tip to tip/23.md.
|
| < | < | | | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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 | # TIP 23: Tk Toolkit Functional Areas for Maintainer Assignments Author: Kevin Kenny <[email protected]> Author: Jim Ingham <[email protected]> Author: Don Porter <[email protected]> Author: Daniel A. Steffen <[email protected]> Author: Donal K. Fellows <[email protected]> State: Accepted Type: Process Vote: Done Created: 22-Jan-2001 Post-History: ----- # Abstract This document proposes a division of the Tk toolkit's source code into functional areas so that each area may be assigned to one or more maintainers. # Background TCT procedures \(see [[0]](0.md)\) call for each _maintainer_ to be responsible for a portion of the Tk toolkit's source code. Certain portions of the Tk toolkit's source code are naturally associated with certain other portions. \(For example, the implementation of a command is intimately related to the documentation for that command.\) Establishing a _natural_ division of the Tk toolkit's source code into units needing maintainers is a useful preliminary effort toward a public call for volunteer maintainers. See [[30]](30.md) for the mapping of these functional areas to maintainers. # Rationale [[16]](16.md) provides a convincing rationale for establishing a simple mapping from source files to maintainers. It also breaks out maintainers' functional areas for the Tcl core. This document attempts to develop a similar mapping for the Tk toolkit. Just as with [[16]](16.md), this document attempts to divide the Tk toolkit into a set of the smallest sensible functional units. One other factor, which was not addressed in [[16]](16.md), is that there is considerably more platform dependent code in Tk than in Tcl, and it is unreasonable to expect people to take ownership for pieces of code that run on platforms they don't have access to. However, we want to make sure that the maintainer structure supports the cross-platform nature of Tk. To that end, in any area where there is both generic code, and platform specific code, we propose that maintainers can sign up for the generic code _and_ code for one or more platforms. By overlapping the generic code, we ensure that the public interfaces to Tk will stay consistent among the platforms, while not forcing maintainers to presume expertise in code they can't even compile, much less test or understand fully. # Functional Areas The Tk toolkit shall be divided into the following functional units, each to be assigned one or more maintainers. Each area will also be a Category in the SourceForge Tracker for Tk: ## Widgets 1. **Bindings** - library/tk.tcl 2. **Appearance** - generic/default.h, macosx/tkMacOSXDefault.h, unix/tkUnixDefault.h, win/tkWinDefault.h 3. **[*button] and [label]** - doc/button.n, doc/checkbutton.n, doc/label.n, doc/radiobutton.n, generic/tkButton.c, generic/tkButton.h, library/button.tcl, macosx/tkMacOSXButton.c, unix/tkUnixButton.c, tests/butGeom.tcl, tests/butGeom2.tcl, tests/button.test, tests/unixButton.test, tests/winButton.test, win/rc/buttons.bmp, win/tkWinButton.c 4. **Canvas Basics** - doc/CanvPsY.3, doc/CanvTxtInfo.3, doc/CanvTkwin.3, doc/CrtItemType.3, doc/GetDash.3, doc/canvas.n, generic/tkCanvUtil.c, generic/tkCanvas.c, generic/tkCanvas.h, tests/canvas.test 5. **Canvas Items** - generic/tkCanvArc.c, generic/tkCanvBmap.c, generic/tkCanvImg.c, generic/tkCanvLine.c, generic/tkCanvPoly.c, generic/tkCanvText.c, generic/tkCanvWind.c, generic/tkRectOval.c, tests/arc.tcl, tests/canvImg.test, tests/canvRect.test, tests/canvText.test, tests/canvWind.test 6. **Canvas PostScript** - generic/prolog.ps, generic/tkCanvPs.c, library/prolog.ps, tests/canvPs.test, tests/canvPsArc.tcl, tests/canvPsBmap.tcl, tests/canvPsGrph.tcl, tests/canvPsImg.tcl, tests/canvPsText.tcl 7. **[entry]** - doc/entry.n, generic/tkEntry.c, library/entry.tcl, tests/entry.test 8. **[frame], [toplevel] and [labelframe]** \(see [[18]](18.md)\) - doc/frame.n, doc/labelframe.n, doc/toplevel.n, generic/tkFrame.c, tests/frame.test 9. **[listbox]** - doc/listbox.n, generic/tkListbox.c, library/listbox.tcl, tests/listbox.test 10. **Generic Menus** - doc/menu.n, doc/menubutton.n, doc/popup.n, generic/tkMacWinMenu.c, generic/tkMenu.c, generic/tkMenu.h, generic/tkMenuDraw.c, generic/tkMenubutton.c, generic/tkMenubutton.h, library/menu.tcl, library/tearoff.tcl, tests/menu.test, tests/menuDraw.test, tests/menubut.test 11. **Aqua Menus** - macosx/tkMacOSXMenu.c, macosx/tkMacOSXMenu.r, macosx/tkMacOSXMenubutton.c, macosx/tkMacOSXMenus.c 12. **Unix Menus** - tests/unixMenu.test, unix/tkUnixMenu.c, unix/tkUnixMenubu.c 13. **Win Menus** - tests/winMenu.test, win/tkWinMenu.c 14. **[message]** - doc/message.n, generic/tkMessage.c, tests/message.test 15. **[scale]** - doc/scale.n, generic/tkScale.c, generic/tkScale.h, library/scale.tcl, macosx/tkMacOSXScale.c, tests/scale.test, unix/tkUnixScale.c 16. **[scrollbar]** - doc/scrollbar.n, generic/tkScrollbar.c, generic/tkScrollbar.h, library/scrlbar.tcl, macosx/tkMacOSXScrlbr.c, tests/scrollbar.test, unix/tkUnixScrlbr.c, win/tkWinScrlbr.c 17. **[spinbox]** - doc/spinbox.n, library/spinbox.tcl, tests/spinbox.test 18. **[text]** - doc/text.n, generic/tkText.c, generic/tkText.h, generic/tkTextBTree.c, generic/tkTextDisp.c, generic/tkTextImage.c, generic/tkTextIndex.c, |
︙ | ︙ | |||
227 228 229 230 231 232 233 | tests/textDisp.test, tests/textImage.test, tests/textIndex.test, tests/textMark.test, tests/textTag.test, tests/textWind.test | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 | tests/textDisp.test, tests/textImage.test, tests/textIndex.test, tests/textMark.test, tests/textTag.test, tests/textWind.test 19. **Menubars \(obsolete\)** - doc/menubar.n, library/obsolete.tcl 20. **[tk_optionMenu]** - doc/optionMenu.n, library/optMenu.tcl 21. **[panedwindow]** \(see [[41]](41.md)\) - doc/panedwindow.n, generic/tkPanedWindow.c, library/panedwindow.tcl, tests/panedwindow.test 22. **Style Engine** \(see [[48]](48.md)\) - generic/tkStyle.c ## Widget Options 23. **Option Parsing** - doc/ConfigWidg.3, doc/SetOptions.3, generic/tkConfig.c, generic/tkOldConfig.c, macosx/tkMacOSXConfig.c, unix/tkUnixConfig.c, tests/config.test, win/tkWinConfig.c 24. **Relief** - doc/3DBorder.3, doc/GetRelief.3, generic/tk3d.c, generic/tk3d.h, unix/tkUnix3d.c, tests/bevel.tcl, tests/border.test, win/tkWin3d.c 25. **Built-in Bitmaps** - bitmaps/error.bmp, bitmaps/gray12.bmp, bitmaps/gray25.bmp, bitmaps/gray50.bmp, bitmaps/gray75.bmp, bitmaps/hourglass.bmp, bitmaps/info.bmp, bitmaps/questhead.bmp, bitmaps/question.bmp, bitmaps/warning.bmp, doc/GetBitmap.3, generic/tkBitmap.c, macosx/tkMacOSXBitmap.c, tests/bitmap.test 26. **Conversions From String** - doc/GetAnchor.3, doc/GetCapStyl.3, doc/GetJoinStl.3, doc/GetJustify.3, doc/GetPixels.3, doc/GetUid.3, generic/tkGet.c, tests/get.test 27. **Objects** - generic/tkObj.c, tests/obj.test 28. **Utility Functions** - doc/DrawFocHlt.3, doc/GetScroll.3, generic/tkUtil.c, tests/util.test 29. **Colormaps and Visuals** - doc/GetClrmap.3, doc/GetVisual.3, generic/tkVisual.c, tests/visual.test 30. **Color Names** - doc/GetColor.3, doc/colors.n, generic/tkColor.c, generic/tkColor.h, macosx/tkMacOSXColor.c, unix/tkUnixColor.c, tests/cmap.tcl, tests/color.test, win/tkWinColor.c, xlib/xcolors.c 31. **Cursor Names** - doc/GetCursor.3, doc/cursors.n, generic/tkCursor.c, macosx/tkMacOSXCursor.c, macosx/tkMacOSXCursors.r, macosx/tkMacOSXXCursors.r, unix/tkUnixCursor.c, tests/cursor.test, win/rc/cursor\*.cur, win/tkWinCursor.c, xlib/X11/cursorfont.h 32. **Key Symbols** - doc/keysyms.n, macosx/tkMacOSXKeyboard.c, unix/tkUnixKey.c, win/tkWinKey.c, xlib/X11/keysym.h, xlib/X11/keysymdef.h ## Standard Dialogs 33. **Generic Dialog Support** - library/comdlg.tcl 34. **[tk_chooseColor]** - doc/chooseColor.n, library/clrpick.tcl, tests/clrpick.test 35. **[tk_dialog]** - doc/dialog.n, library/dialog.tcl, macosx/tkMacOSXDialog.c, tests/dialog.test, tests/winDialog.test, unix/tkUnixDialog.c, win/tkWinDialog.c 36. **[tk_chooseDirectory]** - doc/chooseDirectory.n, library/choosedir.tcl, tests/choosedir.test 37. **[tk_get*File]** - doc/getOpenFile.n, generic/tkFileFilter.c, generic/tkFileFilter.h, library/tkfbox.tcl, library/xmfbox.tcl, tests/filebox.test, tests/xmfbox.test 38. **[tk_messageBox]** - doc/messageBox.n, library/msgbox.tcl, tests/msgbox.test ## Images 39. **Image Basics** - doc/CrtImgType.3, doc/DeleteImg.3, doc/GetImage.3, doc/ImgChanged.3, doc/NameOfImg.3, doc/image.n, generic/tkImage.c, generic/tkImgUtil.c, generic/tkStubImg.c, tests/image.test 40. **Bitmap Images** - doc/bitmap.n, generic/tkImgBmap.c, tests/imgBmap.test 41. **Photo Images** - doc/CrtPhImgFmt.3, doc/FindPhoto.3, doc/photo.n, generic/tkImgPhoto.c, tests/imgPhoto.test 42. **Photo Image\|GIF** - generic/tkImgGIF.c 43. **Photo Image\|PPM** - generic/tkImgPPM.c, tests/imgPPM.test ## Fonts 44. **Generic Fonts** - doc/FontId.3, doc/GetFont.3, doc/MeasureChar.3, doc/TextLayout.3, doc/font.n, generic/tkFont.c, generic/tkFont.h, tests/font.test 45. **Aqua Fonts** - macosx/tkMacOSXFont.c 46. **Unix Fonts** - tests/unixFont.test, unix/tkUnixFont.c, unix/tkUnixRFont.c 47. **Win Fonts** - tests/winFont.test, win/tkWinFont.c ## Geometry management 48. **Geometry Management** - doc/GeomReq.3, doc/MaintGeom.3, doc/ManageGeom.3, generic/tkGeometry.c, tests/geometry.test 49. **[grid]** - doc/grid.n, generic/tkGrid.c, tests/grid.test 50. **[pack]** - doc/pack-old.n, doc/pack.n, generic/tkPack.c, tests/oldpack.test, tests/pack.test 51. **[place]** - doc/place.n, generic/tkPlace.c, tests/place.test ## Selection and Clipboard 52. **[clipboard]** - doc/Clipboard.3, doc/clipboard.n, generic/tkClipboard.c, macosx/tkMacOSXClipboard.c, tests/clipboard.test, tests/unixSelect.test, tests/winClipboard.test, unix/tkUnixSelect.c, win/tkWinClipboard.c 53. **[selection]** - doc/ClrSelect.3, doc/CrtSelHdlr.3, doc/GetSelect.3, doc/OwnSelect.3, doc/selection.n, generic/tkSelect.c, generic/tkSelect.h, tests/select.test ## Other Tk commands 54. **[console]** - doc/console.n, generic/tkConsole.c, library/console.tcl 55. **[focus]** - doc/focus.n, generic/tkFocus.c, tests/focus.test 56. **[grab] and [tk busy]** - doc/Grab.3, doc/busy.n doc/grab.n, generic/tkBusy.c, generic/tkBusy.h, generic/tkGrab.c, tests/busy.test, tests/grab.test 57. **[option]** - doc/AddOption.3, doc/GetOption.3, doc/option.n, generic/tkOption.c, tests/option.file1, tests/option.file2, tests/option.test 58. **[send]** - doc/SetAppName.3, doc/send.n, macosx/tkMacOSXSend.c, tests/send.test, tests/unixSend.test, tests/winSend.test, unix/tkUnixSend.c, win/tkWinSend.c 59. **[tk_focus*]** - doc/focusNext.n, library/focus.tcl, tests/focusTcl.test 60. **[tk_setPalette]** - doc/palette.n, library/palette.tcl 61. **Safe Tk** - doc/loadTk.n, library/safetk.tcl, tests/safe.test ## Low-level Tk functions 62. **Geometry Functions** - generic/tkTrig.c 63. **Tk\_Win Functions** - doc/ConfigWind.3, doc/CrtWindow.3, doc/IdToWindow.3, doc/MainWin.3, doc/MapWindow.3, doc/Name.3, doc/Restack.3, doc/SetClass.3, doc/SetClassProcs.3, doc/SetVisual.3, doc/StrictMotif.3, doc/Tk\_Init.3, doc/WindowId.3, generic/tkWindow.c, tests/window.test 64. **Graphic Contexts** - doc/GetGC.3, generic/tkGC.c 65. **Generic Window Operations** - doc/CoordToWin.3, doc/FreeXId.3, doc/GetHINSTANCE.3, doc/GetHWND.3, doc/GetPixmap.3, doc/GetRootCrd.3, doc/GetVRoot.3, |
︙ | ︙ | |||
600 601 602 603 604 605 606 | tests/id.test, tests/raise.test, tests/tk.test, tests/winfo.test, tests/wm.test, xlib/xgc.c | | | | | | | | | | | | | | | | 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 | tests/id.test, tests/raise.test, tests/tk.test, tests/winfo.test, tests/wm.test, xlib/xgc.c 66. **Aqua Window Operations** - macosx/tkMacOSXCarbonEvents.c macosx/tkMacOSXDebug.c macosx/tkMacOSXDebug.h macosx/tkMacOSXDraw.c, macosx/tkMacOSXEmbed.c, macosx/tkMacOSXEvent.c macosx/tkMacOSXEvent.h macosx/tkMacOSXHLEvents.c, macosx/tkMacOSXKeyEvent.c macosx/tkMacOSXMouseEvent.c macosx/tkMacOSXNotify.c macosx/tkMacOSXRegion.c, macosx/tkMacOSXSubwindows.c, macosx/tkMacOSXWindowEvent.c macosx/tkMacOSXWm.c, macosx/tkMacOSXWm.h, macosx/tkMacOSXXStubs.c 67. **Unix Window Operations** - tests/unixEmbed.test, tests/unixWm.test, unix/tkUnix.c, unix/tkUnixDraw.c, unix/tkUnixEmbed.c, unix/tkUnixEvent.c, unix/tkUnixFocus.c, unix/tkUnixWm.c, unix/tkUnixXId.c 68. **Win Window Operations** - tests/winWm.test, win/stubs.c, win/tkWinDraw.c, win/tkWinEmbed.c, win/tkWinImage.c, win/tkWinPixmap.c, win/tkWinPointer.c, win/tkWinRegion.c, win/tkWinWindow.c, win/tkWinWm.c, win/tkWinX.c 69. **Events** - doc/BindTable.3, doc/event.n, generic/tkBind.c, tests/bind.test 70. **Event Loop** - doc/CrtCmHdlr.3, doc/CrtGenHdlr.3, doc/EventHndlr.3, doc/HandleEvent.3, doc/MainLoop.3, doc/QWinEvent.3, doc/RestrictEv.3, generic/tkEvent.c, tests/event.test 71. **Error Handling** - doc/CrtErrHdlr.3, doc/tkerror.n, generic/tkError.c, library/bgerror.tcl, tests/bgerror.test 72. **Atoms** - doc/InternAtom.3, generic/tkAtom.c, xlib/X11/Xatom.h ## Shells 73. **Argv Parsing** - doc/ParseArgv.3, generic/tkArgv.c 74. **Application Embedding** - doc/Tk\_Main.3, generic/tkInitScript.h, generic/tkMain.c, macosx/tkMacOSXInit.c, unix/tkUnixInit.c, win/tkWin32Dll.c, win/tkWinInit.c, tests/main.test 75. **wish** - doc/wish.1, macosx/tkMacOSXAppInit.c, unix/tkAppInit.c, win/winMain.c ## Demonstrations 76. **Widget Tour** - library/demos/arrow.tcl, library/demos/bind.tcl, library/demos/bitmap.tcl, library/demos/button.tcl, library/demos/check.tcl, library/demos/clrpick.tcl, library/demos/colors.tcl, |
︙ | ︙ | |||
751 752 753 754 755 756 757 | library/demos/images/gray25.bmp, library/demos/images/letters.bmp, library/demos/images/noletter.bmp, library/demos/images/pattern.bmp, library/demos/images/tcllogo.gif, library/demos/images/teapot.ppm | | | | | | | | | | | | | | | | | | | | | | | | | | 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 | library/demos/images/gray25.bmp, library/demos/images/letters.bmp, library/demos/images/noletter.bmp, library/demos/images/pattern.bmp, library/demos/images/tcllogo.gif, library/demos/images/teapot.ppm 77. **Square Demo** - generic/tkSquare.c, library/demos/square 78. **Other Demos** - library/demos/browse, library/demos/hello, library/demos/ixset, library/demos/rmt, library/demos/rolodex, library/demos/tcolor, library/demos/timer ## Localization 79. **L10N** - library/msgs/cs.msg, library/msgs/de.msg, library/msgs/el.msg, library/msgs/en.msg, library/msgs/en\_gb.msg, library/msgs/es.msg, library/msgs/fr.msg, library/msgs/it.msg, library/msgs/nl.msg, library/msgs/ru.msg ## Release Engineering 80. **Release Notes** - README, */README, */\*/README, changes, license.terms, doc/options.n, doc/tk4.0.ps, tests/bugs.tcl 81. **Portability** - compat/limits.h, compat/stdlib.h, compat/unistd.h 82. **X11 Emulation** - xlib/X11/X.h, xlib/X11/Xfuncproto.h, xlib/X11/Xlib.h, xlib/X11/Xutil.h, xlib/xbytes.h, xlib/xdraw.c, xlib/ximage.c, xlib/xutil.c 83. **Mac OS X Build** - macosx/Makefile, macosx/buildTkConfig.tcl, macosx/tkAboutDlg.r, macosx/tkMacOSX.h, macosx/tkMacOSXAETE.r, macosx/Wish.pbproj/project.pbxproj 84. **Unix Build** - unix/Makefile.in, unix/aclocal.m4, unix/configure.in, unix/install-sh, unix/tcl.m4, unix/tk.spec, unix/tkConfig.sh.in 85. **Win Build** - win/Makefile.in, win/aclocal.m4, win/buildall.vc.bat, win/configure.in, win/makefile.vc, win/mkd.bat, win/nmakehlp.c, win/rc/tkc, win/rc/tk\_base.rc, win/rc/wish.exe.manifest, win/rc/wish.rc, win/rmd.bat, win/rules.vc, win/tcl.m4, win/tkConfig.sh.in, win/tkWin.h 86. **Test Tools** - generic/tkTest.c, macosx/tkMacOSXTest.c, win/tkWinTest.c, tests/all.tcl, tests/defs.tcl, tests/visual\_bb.test 87. **Logos** - library/images/logo.eps, library/images/logo100.gif, library/images/logo64.gif, library/images/logoLarge.gif, library/images/logoMed.gif, library/images/pwrdLogo.eps, library/images/pwrdLogo100.gif, library/images/pwrdLogo150.gif, library/images/pwrdLogo175.gif, library/images/pwrdLogo200.gif, library/images/pwrdLogo75.gif, library/images/tai-ku.gif, macosx/Wish.icns, win/lamp.bmp, win/rc/tk.ico, win/rc/wish.ico ## Themed Tk \(Ttk\) 88. **Themed Tk** - doc/ttk\_\*, generic/ttk/\*, library/ttk/\*, tests/ttk/\*, macosx/ttkMacOSXTheme.c, win/ttkWinMonitor.c, win/ttkWinTheme.c, win/ttkWinXPTheme.c # Shared Files The following files are shared by all of Tk. Any maintainer may modify them as necessary to complete changes they are making to their portion of Tk. Some of the following files define Tk's API and should be changed only with TCT approval. * ChangeLog, |
︙ | ︙ | |||
903 904 905 906 907 908 909 | macosx/tkMacOSXInt.h, macosx/tkMacOSXPort.h, unix/tkUnixInt.h, unix/tkUnixPort.h, win/tkWinInt.h, win/tkWinPort.h | | | | | | | | | | | | | | > | 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 | macosx/tkMacOSXInt.h, macosx/tkMacOSXPort.h, unix/tkUnixInt.h, unix/tkUnixPort.h, win/tkWinInt.h, win/tkWinPort.h # Generated Files The following files are generated, so they don't need maintainers. * generic/ks\_names.h, generic/tkDecls.h, generic/tkIntDecls.h, generic/tkIntPlatDecls.h, generic/tkIntXlibDecls.h, generic/tkPlatDecls.h, generic/tkStubInit.c, library/demos/tclIndex, library/tclIndex, unix/configure, unix/mkLinks, win/configure # Platform Dependencies In addition to the division into functional areas, responsibility for a given area can also be qualified by one or more _platform_ specifiers. Some areas, like **Windows Configuration and Build Tools** are obviously platform specific, so the qualification is unnecessary. Others, like **Canvas Items**, are wholly generic. But others, like **Button**, **Scale** or **Scrollbar** contain code for all platforms. A maintainer can sign up for one of these latter areas, but specify support for only one platform. This means that that person will be responsible for the generic code in this area, in conjunction with the other platform maintainers in this area, and the platform specific code in that area. The point behind sharing the generic code among all the maintainers is so that any changes to the Tk visible face of the widget be designed in concert for all platforms. Therefore, it is the responsibility of a platform maintainer for one platform who is sponsering a new feature for that area to work with the other platform maintainers to ensure that the feature is implemented on all platforms. One of the strengths of Tk is its cross-platform nature, and one of the maintainer's jobs is to ensure that this continues. Procedurally, the maintainer will be listed as **Button Widget - Mac OS X**, etc. A maintainer for a given area can sign up for one or more platforms. Due to the good design of the Tk's platform dependencies, determining which files are generic, and which are platform specific is trivial. The generic ones are in the _generic_ directory, the Mac ones in the _macosx_ directory, etc. Similarly, an area which has NO files in the macosx, win, or unix directories is a generic area, and no qualifiers are needed. # Copyright This document has been placed in the public domain. |
Name change from tip/230.tip to tip/230.md.
|
| < | < | | | | | | | | | > | | | | | | | | | 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 | # TIP 230: Tcl Channel Transformation Reflection API Author: Andreas Kupries <[email protected]> Author: Andreas Kupries <[email protected]> Author: Andreas Kupries <[email protected]> State: Final Type: Project Vote: Done Created: 02-Nov-2004 Post-History: Tcl-Version: 8.6 ----- # Abstract This document describes an API which reflects the Channel Transformation API of the core I/O system up into the Tcl level, for the implementation of channel transformations in Tcl. It is built on top of [[208]](208.md) \('Add a chan command'\) and also an independent companion to [[219]](219.md) \('Tcl Channel Reflection API'\) and [[228]](228.md) \('Tcl Filesystem Reflection API'\). As the latter TIPs bring the ability of writing channel drivers and filesystems in Tcl itself so this TIP provides the facilities for the implementation of new channel transformations in Tcl. This document specifies version _1_ of the transformation reflection API. # Background and Motivation The purpose of this and the other reflection TIPs is to provide all the facilities required for the creation and usage of wrapped files \(i.e. virtual filesystems attached to executables and binary libraries\) within the core. While it is possible to implement and place all the proposed reflectivity in separate and external packages, this however means that the core itself cannot make use of wrapping technology and virtual filesystems to encapsulate and attach its own data and library files to itself. Something which is desirable as it can make the deployment and embedding of the core easier, due to having less files |
︙ | ︙ | |||
57 58 59 60 61 62 63 | of the special test commands for exercising the various internal of the Tcl core during test. This TIP asks to make that mechanism publicly available to script and package authors, with a bit of cleanup regarding the Tcl level API. The roots of that mechanism can be traced back to the Trf package which implemented channel transformations first and provides a similar command. | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 | of the special test commands for exercising the various internal of the Tcl core during test. This TIP asks to make that mechanism publicly available to script and package authors, with a bit of cleanup regarding the Tcl level API. The roots of that mechanism can be traced back to the Trf package which implemented channel transformations first and provides a similar command. # Transform Management API Specification The Tcl level API consists of two new subcommands added to the ensemble command **chan**' specified by [[208]](208.md). Both subcommands are completely generic, i.e. they can be applied to any type of channel, without restrictions. There is no C API to specify. The Tcl core already has a standard API for the creation of channel transformations from the C level. ## The push Subcommand > **chan push** _channel cmdprefix_ This subcommand creates a new script level transformation using the command prefix _cmdprefix_ as its handler and attaches it to the specified channel. The new transformation is always added on top of any other transformations which may be present. The handle of the new transformation is returned as the result of the command. This handle is the first argument given to all handler methods, to allow the code to distinguish between the various instances of the same transformation, if necessary. Use the new **chan pop** command to remove the transformation. See below. The API this handler has to provide is specified below, in the section "Command Handler API Specification". We have chosen to use _late-binding_ of the handler command. See the section "Early- versus Late-Binding of the Handler Command" for more detailed explanations. The command invokes the handler method **initialize** to determine the supported methods before it pushes the transformation. It will throw an error if a read-only transformation is pushed on a write-only channel, or vice versa. In general if the r/w-mode of transformation and channel together cause the result to be neither readable nor writable. ## The pop Subcommand > **chan pop** _channel_ This subcommand removes the topmost transformation from the _channel_, if there is any. This command is equivalent to the builtin command _close_ if the channel had no transformations added to it. Note: If the removal of the topmost transformation uncovers inactive transformations \(See section "Interaction with Threads and Other Interpreters"\), then these will be removed now as well. # Command Handler API Specification The Tcl-level handler command for a reflected channel transformation is an ensemble that has to support the following subcommands, as listed below. Note that the term _ensemble_ is used to generically describe all command \(prefixes\) which are able to process subcommands. This TIP is **not** tied to the recently introduced 'namespace ensemble's \(though they may be used to implement such handlers.\) ## The initialize Subcommand > _handler_ **initialize** _handle mode_ This method is called first, and then never again \(for the given _handle_\). Its responsibility is to initialize all parts of the transformation at the Tcl level. The MODE is a list containing any of **read** and **write**. * **write** contained in _mode_ implies that the channel is writable. * **read** contained in _mode_ implies that the channel is readable. The return value of the method has to be a list containing the names of all methods which are supported by this handler. Any error thrown by the method will prevent the creation of the transformation. The thrown error will appear as error thrown by **chan push**. The current version is _1_. This method has no equivalent at the C level. ## The finalize Subcommand > _handler_ **finalize** _handle_ This method is called last for the given _handle_, just before the destruction of the C level data structures. It is now its responsibility to clean up all parts of the transformation at the Tcl level. Any result returned by the method will be ignored. The same is true for errors thrown by the method. This method has no equivalent at the C level. ## The flush Subcommand > _handler_ **flush** _handle_ This method is called whenever data in the transformation 'write' buffer has to be forced downward, i.e. towards the base channel. The result returned by the method is taken as the _binary_ data to write to the transformation below the current transformation. This can be the base channel as well. In other words, when this method is called the transformation cannot defer the actual transformation operation anymore and has to transform all data waiting in its internal write buffers and return the result of that action. The method is optional. However if this method is supported then **write** has to be supported as well. The reverse is not true. ## The write Subcommand > _handler_ **write** _handle buffer_ This method is optional. If it is not present it means that the transformation does not support writing, and the channel it was pushed on becomes non-writable as well. It will be called whenever the user, or a transformation above this transformation writes data downward. The _buffer_ contains the **binary** data which has been written to us. It is the responsibility of this method to actually transform the data. The result returned by the method is taken as the **binary** data to write to the transformation below this transformation. This can be the base channel as well. Note that the result is allowed to be empty, or less than the data we got. The transformation is not required to transform everything which was written to it right now. It is allowed to store this data in internal buffers and to defer the actual transformation until it has more data. ## The drain Subcommand > _handler_ **drain** _handle_ This method is called whenever data in the transformation input \(i.e. read\) buffer has to be forced upward, i.e. towards the user, i.e. the script. The result returned by the method is taken as the **binary** data to push upward to the transformation above this transformation. This can be the script as well. In other words, when this method is called the transformation cannot defer the actual transformation operation anymore and has to transform all data waiting in its internal read buffers and return the result of that action. The method is optional. However if this method is supported then **read** has to be supported as well. The reverse is not true. ## The read Subcommand > _handler_ **read** _handle buffer_ This method is optional. If it is not present it means that the transformation does not support reading, and the channel it was pushed on becomes non-readable as well. It is called whenever the base channel, or a transformation below this transformation pushes data upward. The _buffer_ contains the **binary** data which has been given to us from below. It is the responsibility of this method to actually transform data. The result returned by the method is taken as the **binary** data to push further upward to the transformation above this transformation. This can be the user, i.e. the script as well. Note that the result is allowed to be empty, or even less than the data we got. The transformation is not required to transform everything given to it right now. It is allowed to store incoming data in internal buffers and to defer the actual transformation until it has more data. ## The limit? Subcommand > _handler_ **limit?** _handle_ This method is optional. If it is not present it means that the transformation is allowed to read ahead as much as it likes. This method is called during input processing and allows the Tcl level part of the transformation to restrict the number of bytes read from the downward transformation or base channel before its method **read** is called with the resulting buffer. The result of the method has to be an integer number not equal to zero. A negative result signals that the transformation allows the I/O system to read an unlimited number of bytes. A positive number on the other hand is interpreted as the maximum number of bytes the I/O system is allowed to read from the downward transformation or base channel. This method is necessary for transformations where the data is bounded at the end in some way. In that case the transformation has to prevent the system from reading beyond the boundary as otherwise data behind it will be given to the transformation and then lost when the transformation is removed. **This is a limitation of the current I/O core** as it does not allow a transformation to push unused data back into the I/O core when the transformation is removed from the channel. Fixing this **limitation** requires a separate TIP, as either the public API of the I/O core has to be extended, or the public structure of channel drivers. ## The clear Subcommand > _handler_ **clear** _handle_ This method is called to clear any data stored in the internal input buffers of the transformation. This happens only when the user seeks the channel the transformation is attached to. Any result returned by the method is ignored. The method is optional. I.e. a transformation not having any internal buffers to clear can leave out its implementation. # Hardwired Behavior of Reflected Transformations Not all functions of the channel driver implementing the reflected transformation are directly reflected into the Tcl level. Their behavior is hardwired in the C level implementing the reflection and specified now. BlockModeProc: Records the chosen blocking mode in the C-level data structures. This influences the low-level write and read behavior. However the Tcl level is shielded from this, so a handler method is not required. CloseProc: Invokes the methods **drain** and **flush** to clean up any buffers managed by the Tcl level of the transformation, and then **finalize**. **drain** is not called if a previous call to it has not been invalidated yet. InputProc: Tries to satisfies the incoming read request from the input result buffer first. If that is not enough it invokes the **limit?** method to establish the current read limit, reads data from the downward transformation or base channel per the limit and feeds the data it got to the Tcl level of the transformation, via an invocation of the method **read**. The result of that call is added to the input result buffer and used to further satisfy the read request. > If the channel is blocking the system will iterate until the request is fulfilled completely or EOF has been signaled from below. > In non-blocking mode however the loop will stop if either the request was fulfilled completely, or if we would block. Note that reaching EOF in this situation causes a flush of the Tcl side input buffers via an invocation of the method **drain**. Otherwise the data stored in them would be lost when the transformation is removed or the channel closed completely. OutputProc: Simply forwards the written buffer to the method **write** for processing and then writes any returned result to the transformation or base channel below. SeekProc: Recognizes requests made by **tell** and passes them down without doing anything else. The result generated by the base channel is then passed back up unchanged. > Any other request causes it to flush all write buffers on the Tcl side via an invocation of the method **flush**, and clear all input buffers on the Tcl side via an invocation of the method **clear** before passing the request down. Note that the calls mentioned above are not made if the channel is not writable, or not readable. Further note that the results of the **flush** are discarded, not written, as they would otherwise move the current location and throw off our expectations regarding where we are now and will end up after the seek. > This implements the most simple seek behavior as it was found in the very earliest incarnation of the transform reflection functionality, i.e. passing down any seek request unchanged until the base channel is reached. This also means that the internal state of transformations is not adjusted after a seek and may generate bogus results. > The reflection \(actually any transformation\) provided by the package _Trf_ has much more complex seek behavior. This was left out for now to keep the scope of this TIP relatively focused. A follow-up TIP can be written for a deeper discussion of the interaction between seeking and any type of transformation, not only reflected ones. > See <http://www.oche.de/~akupries/soft/trf/trf\_seek.html> for the description of the complex seeking model used by the transformation reflection in Trf. SetOptionProc, GetOptionProc, GetFileHandleProc: The calls are passed down without change, any results are passed back to the caller, again without any changes. > Transformations have no options which can be configured when they are attached to a channel, hence the pass-through and no handler method at the Tcl level. WatchProc: Remembers the interest mask provided by the caller and uses this to manage the internal timer used to generate fake file events when data is buffered. NotifyProc: Manages the internal timer. Will pass the incoming mask of triggered events upward without change. # Interaction with Threads and Other Interpreters Adding a reflected transformation to a channel does not create any restrictions on the sharing of the channel with other interpreters, nor with moving the channel to different interpreters or threads. Like for reflected channels \(See [[219]](219.md) \('Tcl Channel Reflection API'\)\), the implementation ensures that the handler command is always executed in the original interpreter and thread. The latter is done by posting specialized events to the original thread, essentially forwarding driver invocations to the correct thread. When a thread or interpreter is deleted all transformations it owns are deleted as far as possible, and any remnants are marked as dead. The latter occurs only if the channel using the deleted transformation is outside of the deleted thread or interpreter. Such channels will throw errors when accessed, until the offending transformation is removed from them via **chan pop** \(Multiple pop's will be necessary if the deleted transformation sits in the middle of a stack\). # Interaction with Safe Interpreters The new subcommands **push** and **pop** of **chan** are both safe and therefore made accessible to safe interpreters. While **push**ing a transformation arranges for the execution of code this code is always executed within the safe interpreter, even if the channel was moved \(See previous section\). That the data flowing through the channel is modified by the transformation is no problem either, because to attach the transformation to the channel it has to have been given to the safe interpreter in the beginning, in other words, the interpreter doing this already trusted the safe interpreter in some way, and the fact that we can now add a transformation does not change this. Equivalent reasoning applies if the channel was created by the safe interpreter and then shared/moved into the trusted interpreter. The transformation has no effect on the trust already given to the safe interpreter through the share/move operation. The same holds for the subcommand **pop**. If the safe interpreter can execute it on a channel it has the channel already in its possession, either because it created the channel, or because the channel was shared/moved into it. # Event processing It is specified that reflected transformations do not support any type of user-visible event handling. The only event handling done is the invisible passing of current interest from higher to lower layers, and the \(again invisible\) behaviour needed to drive the flushing of transformation buffers to higher layers. See the descriptions of _WatchProc_ and _NotifyProc_ in the section **Hardwired Behavior of Reflected Transformations**. This is different from the previous revisions of this TIP which included language and definitions to support event processing by transformations up to and including revision 1.11, i.e. allowing transformations to register interest in events, and then process them. The main example use case for this was that it would give a transformation the ability to initialize itself with data coming from the channel \(like a key exchange\) before switching to the plain transformative behaviour. While working on the design of how to support this on the Tcl script level I ran into lots of complicated edge cases and convolutions. Based on this I have now come to the belief that this has been a misfeature from the beginning and that the use case this was based on \(see above\) is an example of comingling concerns which should be separate, i.e an example of what should not be done. The transformation's concern is transforming data, nothing else. Any parameters needed for this, like keys, seeds, etc. should come from the outside, at the time it is pushed on the channel stack. Initializations like key exchanges, cipher negotiations, etc. should and are not be a concern of the transformation. They should and can be done **before** the transformation is configured and pushed. This last means that the removal of user-visible event handling support is by no means a restriction on the type of things we can do. Even so, should we find other use cases for event handling by transformations we can always write another TIP within which we specify how to extend reflected transformations with that feature. # Early- versus Late-Binding of the Handler Command We have two principal methods for using the handler command. These are called early- and late-binding. **Early-binding** means that the command implementation to use is determined at the time of the creation of the channel, i.e. when _chan push_ is executed, before any methods are called. Afterward it cannot change. The result of the command resolution is stored internally and used until the channel is destroyed. Renaming the handler command has no effect. In other words, the system will automatically call the command under the new name. The destruction of the handler command is intercepted and causes the channel to close as well. **Late-binding** means that the handler command is stored internally essentially as a string, and this string is mapped to the implementation to use for each and every call to a method of the handler. Renaming the command, or destroying it means that the next call of a handler method will fail, causing the higher level channel command to fail as well. Depending on the method the error message may not be able to explain the reason of that failure. Another problem with the late-binding approach is that the context for the resolution of the command name has to be specified explicitly to avoid problems with relative names. Early-binding resolves once, in the context of the _chan create_. Late-binding performs resolution anywhere where channel commands like _puts_, _gets_, etc. are called, i.e. in a random context. To prevent problems with different commands of the same name in several namespace it becomes necessary to force the usage of a specific fixed context for the resolution. Note that moving a different command into place after renaming the original handler allows the Tcl level to change the implementation dynamically at runtime. This however is not really an advantage over early-binding as the early-bound command can be written such that it delegates to the actual implementation, and that can then be changed dynamically as well. However, despite all this late binding is so far the method of choice for the implementation of callbacks, be they in Tcl, or Tk; and has been chosen for the reflection as well. The context for all handler method invokations is the **global scope**. # Limitations The method **limit?** is required to limit reading from below to prevent reading over transformation specific boundaries. This is a direct consequence of not being able to push unused data back into the I/O core when a transformation is removed. The reflection implements the very simple seek behavior found in the earliest incarnation of this functionality, i.e. passing down any seek request unchanged until the base channel is reached. This also means that the internal state of transformations is not adjusted after a seek and may generate bogus results. The reflection \(actually any transformation\) provided by the package _Trf_ has much more complex seek behavior. This was left out for now to keep the scope of this TIP relatively focused. A follow-up TIP can be written for a deeper discussion of the interaction between seeking and any type of transformation, not only reflected ones. See <http://www.oche.de/~akupries/soft/trf/trf\_seek.html> for the description of the complex seeking model used by the transformation reflection in Trf. # Miscellanea The transform reflection API reserves the driver type "tclrtransform" for itself, and uses it to detect its own transformations. Usage of this driver type by other transformations is not allowed. # Examples ## Transformation Implementations A simple way of implementing new transformations is to use any of the various object systems for Tcl. Create a class for the transformation. **chan push** the transformation in the constructor for new objects and store the transformation handle. Make the new object the command handler for the transformation. This automatically translates the sub commands for the command handler into object methods. Implement the various methods required. When the object is deleted deactivate the transformation, and delete the object when the channel announces that the transformation has been **chan pop**ped. This part is a bit tricky, flags have to be used to break the potential cycle. Another possibility is to implement the command handler as a regular command, together with a creation command wrapping around _chan push_ and a backend which keeps track of all handles created by it and their state, associated data, etc. ## Possible Transformations * Identity * Gathering statistics about the channel. The simplest would be to count bytes, for example. * Divert a copy of all data to a separate channel. In other words, spying on the channel. * Give a channel which normally cannot seek backward the ability to do so through buffering \(a limited amount of\) the data read from it. * Limit reading from a channel to a specific finite number of characters \(This can be done via a suitable implementation of the method "limit?" in the transformation handler\). # Reference Implementation A variant implementation of this TIP is already present in the core, as part of the special test commands for exercising the various internal of the Tcl core during test. The relevant files are * "tclIOGT.c" \(base implementation\) and * "tclTest.c" \(command interface\). The command interface specified here is different from the current interface. test transform channel -command command versus chan push channel cmdprefix chan pop The handler methods are different as well. This TIP consolidated a number of methods, gave them better names and removed unnecessary arguments. It also removed some limitations. The actual reference implementation is provided at SourceForge <http://sourceforge.net/support/tracker.php?aid=1163274> . # Comments [ Add comments on the document here ] # Copyright This document has been placed in the public domain. |
Name change from tip/231.tip to tip/231.md.
|
| < | < | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 231: Support for [wm attributes] on X11 Author: Joe English <[email protected]> State: Final Type: Project Created: 06-Nov-2004 Tcl-Version: 8.5 Vote: Done Post-History: ----- # Abstract This TIP adds three UNIX/X11-specific attributes to the **wm attributes** command to take advantage of features newer Unix window manager control standards. # Specification This TIP proposes to add support for the following window attributes under X11 in the **wm attributes** command: * **-fullscreen** > This attribute has the same meaning as the equivalent option for Windows \(see [[223]](223.md)\) with one restriction \(outlined below\). * **-topmost** > This attribute has the same meaning as the equivalent option for Windows \(see [[95]](95.md)\) with one restriction \(outlined below\). * **-zoomed** > This attribute requests that the window be maximized; it is the same as [**wm state** _win_ **zoomed**] on Windows, subject to the restriction outlined below. # Restrictions Under X11, the **-fullscreen**, **-topmost**, and **-zoomed** attributes require cooperation from the window manager. If the window manager does not support these attributes, setting them will have no effect. In particular, they are not supported by older window managers like MWM and DTWM. Under X11, the **wm attributes** command operates asynchronously: [**wm attributes** _-attribute_] returns the current value of the attribute, which will not be the same as the value most recently set if the window manager has not yet processed the request or if it does not support the attribute. # Reference Implementation See patch \#1062022 <http://sf.net/support/tracker.php?aid=1062022> which is based on the freedesktop.org Extended Window Manager Hints specification <http://www.freedesktop.org/Standards/wm-spec> . # Copyright This document has been placed in the public domain. |
Name change from tip/232.tip to tip/232.md.
|
| < | < | | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | < < > > | < | > | | | | | | < < | > > | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 232: Creating New Math Functions for the 'expr' Command Author: Arjen Markus <[email protected]> Author: Kevin Kenny <[email protected] > State: Final Type: Project Vote: Done Created: 26-Nov-2004 Post-History: Keywords: math,expr,Tcl Tcl-Version: 8.5 ----- # Abstract This TIP proposes to replace Tcl's math functions, ordinarily created using the **Tcl\_CreateMathFunc\(\)** function, with ordinary Tcl commands created in a known namespace, **::tcl::mathfunc**. This change has two chief motivations: it allows programmers to define new math functions at the Tcl level, and it encapsulates the **Tcl\_Value** API so that new math functions can work on data types that are not described adequately as **Tcl\_Value** objects. # Rationale The two authors of this TIP, Kevin Kenny and Arjen Markus, have come at wanting the same change to Tcl from two distinct directions. Arjen Markus has been the maintainer of several modules in Tcllib that implement "special functions" such as the exponential integral, the incomplete gamma function and the Bessel functions. He has wanted to have "scripted" math functions available to simplify his notation. In place of a complex expression like set f [expr { $x*[J0 $x] + [J1 [expr {2.0*$x}]] }] which is pretty unreadable \(and prone to error because of the need to brace the subexpressions\), he would like a mechanism for defining new mathematical functions so that he can write: set f [expr { $x*J0($x) + J1(2.0*$x) }] Donal Fellows has felt the need for such a construct, too, enough to implement a "funcproc" extension that provides it. <http://wiki.tcl.tk/541> Kevin Kenny has come at the desire for rework of the math function mechanism from a different direction. He has been investigating Tcl Core support for arbitrary-precision integers [[237]](237.md), and discovered that implementing math functions that accept them as arguments or return them as results would require an incompatible change to the **Tcl\_Value** data type that is used to communicate with the math functions. When the last such change was made \(in implementing 64-bit integers [[72]](72.md)\), it required a source code change to several popular extensions that created new math functions _min_ and _max_. Wishing the incompatibility introduced by [[237]](237.md) to be the last of the type, he decided to eliminate **Tcl\_Value** and use the open-ended **Tcl\_Obj** data type in its place. When he derived the type signature that a math function would have if it accepted its parameters in an array of **Tcl\_Obj** pointers, he discovered that it was identical to the **Tcl\_ObjCmdProc** -- making him ask, "what if math functions really _were_ commands?" This TIP is the result of those two investigations, and proposes a unification of math functions with Tcl commands. # Proposed Changes This TIP proposes that: 1. The [expr] command shall be modified so that an expression of the form: f(arg1,arg2,...) > shall generate code equivalent to that generated by [tcl::mathfunc::f [expr { arg1 }] [expr { arg2 }] ...] > so that math functions are interpreted as Tcl commands whose arguments are parsed as subexpressions. The existing code in [expr] that checks for correct argument counts to the math functions at compile time shall be removed \(the general consensus among Core maintainers is that compile-time checks of this sort are a bad idea anyway\). > Note that the call to _tcl::mathfunc::f_ has no leading namespace delimiter. A search for the function will try to resolve it first relative to the current namespace. 1. The current math functions in Tcl shall be reimplemented as ordinary Tcl commands in the **::tcl::mathfunc** namespace; a Tcl interpreter will contain commands **::tcl::mathfunc::abs**, **::tcl::mathfunc::acos**, etc. 1. The Tcl command [info functions] shall be deprecated in favor of searching for math functions using [info commands] in the appropriate namespace. 1. The C functions **Tcl\_CreateMathFunc**, **Tcl\_GetMathFuncInfo**, and **Tcl\_ListMathFuncs** shall be deprecated in favor of **Tcl\_CreateObjCommand**, **Tcl\_GetCommandInfo** and [info commands]. \(The last is provided only in Tcl at the present time; we do not export a C-level interface to enumerate commands in a namespace.\) The functions will continue to work for extensions that use them. The **Tcl\_CreateMathFunc** command will create a Tcl command in the **::tcl::mathfunc** namespace whose command procedure checks argument count and types and dispatches to the math function handler. The **Tcl\_GetMathFuncInfo** procedure will return _TCL\_OK_ or _TCL\_ERROR_ according to whether the given math function exists in **::tcl::mathfunc** and will return parameter information for \(only\) those functions defined using **Tcl\_CreateMathFunc**. Functions defined as ordinary Tcl commands shall return _TCL\_OK_ but have a parameter count of -1. The **Tcl\_ListMathFuncs** procedure will simply enumerate all the commands in the **::tcl::mathfunc** namespace. 1. Several error messages change as a side effect of changing the math function implementation. All of the new messages are more informative than the old ones \(for instance, identifying which math function encountered a parameter error rather than a generic "too few/too many arguments to math function"\), with the exception of the error message for an unknown function, which is replaced with "unknown command ::tcl::mathfunc::<the\_command>" where <the\_command> is the name of the missing function. # Discussion The proposed change lifts several other restrictions in the way math functions operate: 1. There is no longer any restriction that new math functions must accept a fixed number of arguments, or, indeed, that their arguments and results must be numeric. It will be possible to create variadic functions like: proc ::tcl::mathfunc::min args { set m Inf foreach a $args { if { $a < $m } { set m $a } } return $m } 1. It will be possible to compile Tcl code that refers to a math function that has not yet been defined. That is: proc foo { x } { set have_f [llength [info commands ::tcl::mathfunc::f]] if { $have_f } { return [expr { f($x) }] } else { ... fallback ... } } > will be a valid procedure. \(In Tcl 8.4, the procedure will fail to compile if _f_ is not known at compile time, something that runs contrary to the dynamic nature of Tcl.\) 1. Namespaces will be able to define their own math functions that are not visible outside those namespaces. If a namespace defines a function **[namespace current]::tcl::mathfunc::f**, then calls to **f** in expressions evaluated in that namespace will resolve to it in preference to **::tcl::mathfunc::f**. Not only does this rule allow two extensions both to define functions **f** without collision, but it also allows an extension to override a builtin function such as **sin**. Alas, all these improvements come at some cost of performance. On Kevin Kenny's machine, the command expr {sin(0.325)} executes in roughly 520 nanoseconds before the change, and 870 nanoseconds afterward. Since the resolution of the function name is cached, name lookup is not the problem; rather, the issue is that invoking the function as a command needs to look for command traces; this whole mechanism costs about 300-350 ns \(and has been observed to do so in other contexts\). For real-life expressions, the additional cost tends to vanish quickly into statistical noise; variable access \(with corresponding checks for traces\) and bytecode overhead quickly comes to dominate the performance for all but the simplest expressions. # Safe Interpreters It is not anticipated that exposing this functionality in a safe interpreter will present any new problems for safety. Any functionality that the interpreter can access by defining or overriding math functions is functionality that would have been available to it by calling the functions as commands. # Impact on C-coded Extensions Extensions coded in C that wish to create math functions accepting parameters of type **TCL\_EITHER** may find that they do not get type coercion from parameters of new numeric types, such as extended-precision integers. The coding change to replace them with Tcl commands is fairly easy and mechanical, at a level of effort comparable to that needed for [[72]](72.md). Moreover, once it is completed, a math function will be using the known **Tcl\_CreateObjCmd** API, which has been stable since Tcl 8.0 and is unlikely to change substantially in future releases. The _tbcload_ extension will need to implement a small amount of bytecode translation to preserve compatibility with bytecode compiled modules built against earlier versions of Tcl. The reason is that two bytecodes, **INST\_INVOKE\_BUILTIN1** and **INST\_INVOKE\_FUNC1** have been eliminated from **Tcl\_ExecuteByteCode** since the compiler no longer emits them. If this change for some reason should prove infeasible, we can always put the bytecodes back into **Tcl\_ExecuteByteCode**, but the authors of this TIP would prefer to avoid the code bloat. # Reference Implementation A reference implementation is committed on the 'tcl-numerics-branch' at SourceForge and may be retrieved with cvs -d:ext:[email protected]:/cvsroot/tcl checkout -rTIP232 tcl_numerics # Copyright Copyright \(c\) 2005 by Kevin B. Kenny and Adriaan Markus. All rights reserved. This document may be distributed subject to the terms and conditions set forth in the Open Publication License, version 1.0 <http://www.opencontent.org/openpub/> . |
Name change from tip/233.tip to tip/233.md.
|
| < | < | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 233: Virtualization of Tcl's Sense of Time Author: Andreas Kupries <[email protected]> Author: Andreas Kupries <[email protected]> State: Final Type: Project Vote: Done Created: 30-Nov-2004 Post-History: Tcl-Version: 8.5 ----- # Abstract This document describes a number of changes to internal and public APIs which allows external code to hook into the routines through which the Tcl core computes time-dependent information, and to override them. Through this the external code can manipulate Tcl's sense of time. # Background and Motivation The purpose of this change is to allow code embedding the Tcl core, like simulators of all kind, to manipulate Tcl's sense of time. Currently everything in the core dependent on time, like event handling and all clock operations will always operate in real-time, as the core gets the basic information directly from the operating system. At least in simulators however it can make sense to have Tcl run in the virtual time, and not real-time. This is currently not possible, and this TIP proposes to change this, and how. # Specification At the Tcl level nothing changes. All changes are at the C level, extending and changing existing APIs. Two new functions, **Tcl\_SetTimeProc** and **Tcl\_QueryTimeProc**, are added to the public API of the core. Their signatures are: void Tcl_SetTimeProc(Tcl_GetTimeProc *getProc, Tcl_ScaleTimeProc *scaleProc, ClientData clientData); void Tcl_QueryTimeProc(Tcl_GetTimeProc **getProc, Tcl_ScaleTimeProc **scaleProc, ClientData *clientData); typedef void (Tcl_GetTimeProc) (Tcl_Time *timebuf, ClientData clientData); typedef void (Tcl_ScaleTimeProc) (Tcl_Time *timebuf, ClientData clientData); The first function registers two related handler functions with the core. The first handler function is a replacement for **Tcl\_GetTime**, or rather the OS access made by **Tcl\_GetTime**. The other handler function is used by the Tcl notifier to convert wait/block times from virtual into real time. The second function returns the currently registered handler functions. If no external handlers were set then this will return the handlers accessing and processing the native time of the OS. Any handler pair specified has to return data which is consistent between them. In other words, setting one handler of the pair to something assuming a 10-times slowdown, and the other handler of the pair to something assuming a two-times slowdown is wrong and not allowed. The set handlers are allowed to run the delivered time backwards, however this should be avoided. We have to allow it as the native time can run backwards as the user can fiddle with the system time one way or other. Note that the insertion of the hooks will not change the behaviour of the Tcl core with regard to this situation, i.e. the existing behaviour is retained. The implementations of **Tcl\_GetTime** and **TclpGetClicks** are changed to check for the presence of a handler first, and will ask the operating system for the current time if and only if no handler has been registered. Both use the handler _Tcl\_GetTimeProc_. The implementations of **Tcl\_Sleep**, **Tcl\_WaitForEvent** and **NotifierThreadProc** are changed to check for the presence of a handler as well, and will invoke it with the current wait/block time if it is present. The handler is not invoked if it is either not present, or if no timeout was specified, or if the timeout is zero. Both use the handler _Tcl\_ScaleTimeProc_. # Limitations While the proposed changes are able to change Tcl's view of the current time, and of time intervals, no effort was made to reduce the execution speed of the interpreter itself, i,.e. of the bytecode engine. This means that from the point of view of the virtual time the execution of bytecode has become faster. This can change the relative timing of events. For example the window for a race condition is in virtual time effectively reduced in size by the scaling factor between virtual and real time, becoming less likely. # Reference Implementation A reference implementation is provided at SourceForge <http://sourceforge.net/support/tracker.php?aid=1073863> . # Comments [ Add comments on the document here ] # Copyright This document has been placed in the public domain. |
Name change from tip/234.tip to tip/234.md.
|
| < | < | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 | # TIP 234: Add Support For Zlib Compression Author: Pascal Scheffers <[email protected]> State: Final Type: Project Vote: Done Created: 08-Dec-2004 Post-History: Keywords: Tcl,zip,gzip,deflate Tcl-Version: 8.6 ----- # Abstract This TIP proposes a new core package with commands to handle compression and decompression using the Zlib compression library. # Rationale The Zlib compression algorithm is a widely used method for compression of files and streams. It is the algorithm used for .gz and \(most\) .zip files, as well as one of the standard compression algorithms in the HTTP protocol specifications. Including support for Zlib compression in the core would enable the use of compressed VFS files, fast pure Tcl implementations of gzip and zip utilities and the use of compression in various network protocols. A compressed VFS would be of great benefit to the new **clock** implementation [[173]](173.md), which brings a long a large number of small files which contain the timezone data. Although this would also require support for a VFS file format in the core. One possible candidate would be the Tcl Read Only fs \(trofs\), or perhaps a zip file VFS \(only a tclvfs zip handler exists at the time of writing\). Such a compressed VFS is outside the scope of this TIP, but would be much easier in the future based on top of it. ## History and Implementation Notes The specification and implementation for the package and command originally came from tclkit. This was wrapped in a TEA compliant package as a stand alone package. The reference implementation is a full rewrite, retaining the public API of the tclkit _zlib_ command. The gzip support and C Language API are not part of the original _zlib_ extension. The streaming decompression is functionaly equivalent to tclkit **zlib sinflate**, but uses a different command names. Streaming compression is new. The package version for this release is 2.0 because the private API from the original command has been removed. Alternatively, the package version can be 1.2 indicating new features were added and no existing public APIs were changed. # Dependency Issues The package utilizes zlib/libz from the gzip project <http://www.gzip.org/zlib/> . The license of this project/library is compatible with the Tcl license, and it also compiles on most, if not all, platforms where Tcl compiles. For ease of use, the core distribution shall include a copy of libz under _tcl/contrib_. This copy will be built and used automatically when autoconf cannot find zlib.h during the configure stage. # Streaming For large files \(where large is a relative value, of course\), streaming compression and decompression is required. This is implemented by using temporary commands, which can be fed small amounts of data, yielding small chunks of \(de\)compressed data. # Tcl API ## Block Compression and Decompression There are three compressed formats supported by this command: * _compress_ - the output contains raw deflate data, with no zlib/gzip headers or trailers and no checksum value. * _deflate_ - the output contains data in zlib format, with zlib header and trailer using an Adler-32 checksum * _gzip_ - the output contains data in gzip format, with empty gzip filename, no extra data, no comment, no modification time \(set to zero\), no header crc and the operating system will be set to 255 \(unknown\). Data is treated as binary, meaning that all input and output is going to be converted and treated as byte arrays in Tcl. > **zlib compress** _data_ ?**-level** _level_? Returns raw deflated byte-array version of binary data _data_, at an optional compression _level_. The compression level must be between 0 and 9: 1 gives best speed, 9 gives best compression, 0 gives no compression at all \(the input data is simply copied a block at a time\). > **zlib decompress** _compressedData_ Decompresses a raw deflated byte array as obtained from **zlib compress**. > **zlib deflate** _data_ ?**-level** _level_? Returns zlib-compressed version of _data_, at an optional compression **level**. The compression level must be between 0 and 9: 1 gives best speed, 9 gives best compression, 0 gives no compression at all \(the input data is simply copied a block at a time\). > **zlib inflate** _deflatedData_ Decompresses the zlib-compressed data as obtained from **zlib deflate**. > **zlib gzip** _data_ ?**-level** _level_? ?**-header** _gzipHeaderDict_? Returns gzip-compressed _data_, at an optional compression _level_. The compression level must be between 0 and 9: 1 gives best speed, 9 gives best compression, 0 gives no compression at all \(the input data is simply copied a block at a time\). When header dict is not given with the **-header** option, the gzip header will have no file name, no extra data, no comment, no modification time \(set to zero\), no header crc, and the operating system will be set to 255 \(unknown\). The header dict may contain: * **crc** - integer: CRC-32 of the uncompressed data. * **filename** - string: original file name. * **os** - integer: Operating system/file system used \(see RFC 1952 <http://www.ietf.org/rfc/rfc1952.txt> for list of codes\). * **size** - integer: uncompressed size modulo 2\*\*32. * **time** - integer: unix mtime in seconds since 1970-1-1, suitable for use with **clock format**. * **type** - flag: **binary** for binary data, **text** for "probably text". Other fields may be added in the future. > **zlib gunzip** _gzipData_ ?**-headerVar** _headerDictVarName_? Decompresses the gzip data as obtained from **zlib gzip** or any gzip file. The command returns the uncompressed data. The optional **-headerVar** variable name will be filled with the available header fields. If a field does not exist in the gzip header, it will not be present in the dict. For example, the original filename, comment and crc are optional header fields and will be not set in the dict if they do not exist. Note that **compress**/**decompress**, **deflate**/**inflate** and **gzip**/**gunzip** must be used in pairs. ## Streaming Compression and Decompression Streaming is handled in one of two ways. Either by **push**ing a transformation onto a channel's transformation stack, or by a worker command which is created by calling the **zlib** command's **stream** subcommand. ## Channel Transformations > **zlib push** **deflate**\|**inflate**\|**compress**\|**decompress**\|**gzip**\|**gunzip** _channel_ ?_-level level_? ?_-limit count_? ?_-header gzipHeaderDict_? ?_-headerVar headerDictVarName_? Pushes the requested transformation onto the channel stack. The compression level must be between 0 and 9: 1 gives best speed, 9 gives best compression, 0 gives no compression at all \(the input data is simply copied a block at a time\). The **-limit** option specifies the maximum number of bytes to read from the channel. This is mainly intended to specify how much compressed should be read from a non-seekable channel. The **-header** and **-headerVar** are only used for **gzip** and **gunzip** modes respectively. See the previous section for their definition. Additional **chan** commands are enabled after pushing a zlib transformation: > **chan adler32** _channelId_ Returns the Adler32 checksum for the data. Continuously updated during compression, available only at the of decompression. > **chan fullflush** _channelId_ Performs a fullflush on the compression output. At the end of the data during compression, simply **chan pop** to finalize compression and flush any remaining compressed data. At the end of compressed data, the channel will return EOF until the transformation is popped from the channel. If no **-limit** was specified, the current access position of the channel is undefined. When the base channel or transform returns EOF, compression will automatically finalize. When EOF occurs during decompression but the compressed stream is not yet at EOF, an error will be raised. ## The zlib stream command > **zlib stream** **deflate**\|**inflate**\|**compress**\|**decompress**\|**gzip**\|**gunzip** ?_-level level_? ?_-header gzipHeaderDict_? ?_-headerVar headerDictVarName_? Returns a command name which will perform the requested operation in a streaming fashion. The compression level value, _level_, is only used when compressing data. The **-header** and **-headerVar** are only used for **gzip** and **gunzip** modes respectively. See earlier in this TIP for their definition. ### Stream Worker Command The stream worker command is used to actually compress and decompress in smaller chunks than the input and/or output. > _stream_ **put** ?_-flush\|-fullflush\|-finalize_? _data_ Adds data to be \(de\)compression. The flags **-flush**, **-fullflush** and **-finalize** are mutually exclusive and indicate the desired flushing of the stream. **-finalize** is used to indicate the last block of data while compressing. After **-finalize**, no more data can be added to be compressed. For decompression, after **-finalize** you can still add more data for decompression. > _stream_ **flush** The next invoke of the stream's **get** subcommand will try to get the most data from the stream. While compressing, calling [_stream_ **flush**] often will degrade the compression ratio as it forces all remaining input to be output immediately. > _stream_ **fullflush** Like the **flush** subcommand, the next **get** subcommand invoked on the stream will try to get the most data from the stream. Additionally, the compressor will output extra data to enable recovery from this point in the datastream. > _stream_ **finalize** For compression, this signals the end of the input data; no more data can be added to the stream after the **finalize** subcommand is called. For decompression, this functions the same as the **flush** subcommand. > _stream_ **get** ?**-count** _count_? Gets \(de\)compressed data from the stream. The optional _count_ parameter specifies the maximum number of bytes to read from the stream. Especially for decompression, it is strongly recommended to specify a _count_. > _stream_ **eof** Returns 0 while the end of the compressed stream has not been reached. Returns 1 when the end of compressed stream was reached or the last data has been put to the stream and **-finalize** was specified, or [_stream_ **finalize**] has been called while compressing data. When [_stream_ **eof**] is returning true, and [_stream_ **get** ?_count_?] returns an empty string, you will have obtained all data from the stream. > _stream_ **checksum** Returns the Adler-32 or CRC-32 checksum of the uncompressed data. For compressing streams, this value is updated on each **$stream put**. For decompressing streams, the value will only match the adler32 of the decompressed string after the last [_stream_ **get**] returned an empty string. Which type of checksum is computed \(Adler-32 or CRC-32\) depends on the compression format of the stream. > _stream_ **close** Deletes the _stream_ worker command and all storage associated with it. Discards any remaining input and output. After this command, the _stream_ command cannot be used anymore. ## Checksums > **zlib crc32** _data_ ?**-startValue** _startValue_? Calculates a standard _CRC-32_ checksum, with an optional start value for incremental calculations. > **zlib adler32** _data_ ?**-startValue** _startValue_? Calculates a quick _Adler-32_ checksum, with an optional start value for incremental calculations. # C API ## Synopsys Tcl\_Obj \* **Tcl\_ZlibDeflate**\(_interp, format, data, level, dictObj_\) Tcl\_Obj \* **Tcl\_ZlibInflate**\(_interp, format, data, dictObj_\) unsigned int **Tcl\_ZlibCRC32**\(_initValue, bytes, length_\) unsigned int **Tcl\_ZlibAdler32**\(_initValue, bytes, length_\) int **Tcl\_ZlibStreamInit**\(_interp, mode, format, level, dictObj, zshandlePtr_\) Tcl\_Obj \* **Tcl\_ZlibStreamGetCommandName**\(_zshandle_\) int **Tcl\_ZlibStreamEof**\(_zshandle_\) int **Tcl\_ZlibStreamClose**\(_zshandle_\) int **Tcl\_ZlibStreamAdler32**\(_zshandle_\) int **Tcl\_ZlibStreamPut**\(_zshandle, dataObj, flush_\) int **Tcl\_ZlibStreamGet**\(_zshandle, dataObj, count_\) ## Arguments Tcl\_Interp \*interp \(in\): Optional interpreter to use for error reporting. int format \(in\): Compressed data format. For compression and decompression either **TCL\_ZLIB\_FORMAT\_RAW**, **TCL\_ZLIB\_FORMAT\_ZLIB** or **TCL\_ZLIB\_FORMAT\_GZIP**. A fourth value, **TCL\_ZLIB\_FORMAT\_AUTO** is available for decompression, which can be used when decompressing either GZIP or ZLIB formatted data. Decompression of RAW data requires specifying the format as RAW. int mode \(in\): Compress or decompress mode. Either **TCL\_ZLIB\_INFLATE** or **TCL\_ZLIB\_DEFLATE**. Tcl\_Obj \*data \(in\): The input data for compression or decompression. Will be interpreted as a bytearray object. int level \(in\): The compression level. Must either be between 0 and 9 \(1 gives best speed, 9 gives best compression, 0 gives no compression at all with the input data is simply copied a block at a time\) or -1 to get a default level that balances speed and compressed size. This parameter is ignored by decompressing streams. const char \*bytes \(in/out\): On input, an array of bytes for calculation of checksums or compression/decompression. On output, an array of bytes to copy compressed or decompressed data into. int length \(in\): number of bytes to calculate the checksum on, or the size of _bytes_ buffer to read from or write to. unsigned int initValue \(in\): start value value for the crc-32 or adler-32 calculation. Tcl\_Obj \*dictPtr \(in\): A reference to a dict containing any additional options for the stream handler. This is used to pass options such as **-limit**, **-header**, etc. See the Tcl command documentation for a list of options supported for a particular format and mode. If NULL, will be treated as if it is an empty dict. Tcl\_ZlibStream \*\*zshandlePtr \(out\): Pointer to an integer to receive the handle to the stream. All subsequent _Tcl\_ZlibStream\*_\(\) calls require this handle. Tcl\_ZlibStream \*zshandle \(in\): Handle for the stream. Tcl\_Obj \*dataObj \(in/out\): A bytearray object to read the streamed data from \(**Tcl\_ZlibStreamPut**\) or write the streamed data to \(**Tcl\_ZlibStreamGet**\). int flush \(in\): Flush parameter. **TCL\_ZLIB\_NO\_FLUSH**, **TCL\_ZLIB\_FLUSH**, **TCL\_ZLIB\_FULLFLUSH** or **TCL\_ZLIB\_FINALIZE**. int count \(in\): Maximum number of bytes to be written to the _dataObj_ Tcl\_Obj. The special flag value -1 means get all bytes. ## Functions > **Tcl\_ZlibDeflate\(\)** Depending on the _type_ flag, this function returns a _Tcl\_Obj \*_ with a zero reference count containing the compressed data in either raw deflate format, zlib format or gzip format. If an error happens during compression, this function will return NULL and store a message in the Tcl interpreter. > **Tcl\_ZlibInflate\(\)** This function returns a _Tcl\_Obj \*_ with a zero reference count containing the decompressed data. The _buffersize_ argument may be used as a hint if the decompressed size is know before decompression. If an error happens during decompression, this function will return NULL and store a message in the Tcl interpreter. > **Tcl\_ZlibCRC32\(\)** This function returns the standard CRC-32 calculation. The _startvalue_ should contain the previously returned value for streaming calculations, or zero for the first block. > **Tcl\_ZlibAdler32\(\)** This function returns a quick Adler-32 calculation. The _startvalue_ should contain the previously returned value for streaming calculations, or zero for the first block. > **Tcl\_ZlibStreamInit\(\)** This function initializes the internal state for compression or decompression and creates the Tcl worker command for use at the script level. Returns TCL\_OK when initialization was succesful. > **Tcl\_ZlibStreamGetCommandName\(\)** This function returns a _Tcl\_Obj \*_ which contains the fully qualified stream worker command name associated with this stream. > **Tcl\_ZlibStreamEof\(\)** This function returns 0 or 1 depending on the state of the \(de\)compressor. For decompression, eof is reached when the entire compressed stream has been decompressed. For compression, eof is reached when the stream has been flushed with **TCL\_ZLIB\_FINALIZE**. > **Tcl\_ZlibStreamClose\(\)** This function frees up all memory associated with this stream, deletes the Tcl worker command and discards all remaining input and output data. > **Tcl\_ZlibStreamAdler32\(\)** This function returns the Adler-32 checksum of the uncompressed data up to this point. For decompressing streams, the checksum will only match the checksum of uncompressed data when _Tcl\_ZlibStreamGet_ returns an empty string. > **Tcl\_ZlibStreamPut\(\)** This function is used to copy data to the stream from the given buffer. For compression, the final block of data, which may be an empty string, must be indicated with **TCL\_ZLIB\_FINALIZE** as the flush parameter. The number of bytes read from the supplied buffer is returned \(or -1 on error\). > **Tcl\_ZlibStreamGet\(\)** This function is used to copy the data from the stream to the given buffer. The number of bytes written to the supplied buffer is returned \(or -1 on error\). # Usage Zlib support is to form part of Tcl's standard API: no special measures will be needed for Tcl code or C-implemented extensions to make use of it. # Safe Interpreters These commands only work on data already available to a safe interpreter and are therefore safe make available in the safe interpreter. # Reference Implementation An old version the reference implementation is available at the subversion repository <http://svn.scheffers.net/zlib> . Alternatively, a recent snapshot is available <http://svn.scheffers.net/zlib.tar.gz> . This reference implementation includes a copy of zlib-1.2.1 <http://www.gzip.org> . The reference implementation currently implements a version 1.8 of this TIP. # Copyright This document has been placed in the public domain. |
Name change from tip/235.tip to tip/235.md.
|
| < | < | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 235: Exposing a C API for Ensembles Author: Donal K. Fellows <[email protected]> State: Final Type: Project Vote: Done Created: 10-Dec-2004 Post-History: Tcl-Version: 8.5 ----- # Abstract This TIP exposes a C API for the ensembles of [[112]](112.md). # Rationale As the Tcl core moves to make more use of ensembles, it becomes more necessary for there to be an API available to allow control over those ensembles from the C level so that it is not necessary for such manipulation to be done through the evaluation of Tcl scripts \(e.g. because this interferes with the interpreter's command count and that may be limited in that particular interpreter\). Given such an API, it should be exposed to code outside the Tcl core if at all possible. # Proposed Change This TIP proposes exposing the following functions: Tcl\_CreateEnsemble: Create an ensemble linked to a particular namespace and return the command token for the namespace command. The _flags_ argument specifies the initial version of the set of flags controllable through Tcl\_SetEnsembleFlags \(see below\). > > Tcl\_Command **Tcl\_CreateEnsemble**\(Tcl\_Interp \*_interp_, const char \*_name_, Tcl\_Namespace \*_namespacePtr_, int _flags_\) Tcl\_FindEnsemble: Return a command token for an ensemble, or NULL if the name does not refer to an ensemble. The _flags_ argument controls whether failure to find an ensemble is an error and should be either 0 or TCL\_LEAVE\_ERR\_MSG. > > Tcl\_Command **Tcl\_FindEnsemble**\(Tcl\_Interp \*_interp_, Tcl\_Obj \*_cmdNameObj_, int _flags_\) Tcl\_IsEnsemble: Test whether a command token refers to an ensemble. > > int **Tcl\_IsEnsemble**\(Tcl\_Command _command_\) Tcl\_GetEnsembleSubcommandList, Tcl\_SetEnsembleSubcommandList: Read and write the \(fixed\) list of subcommands of the ensemble. Equivalent to manipulating the **-subcommands** option. > > int **Tcl\_GetEnsembleSubcommandList**\(Tcl\_Interp \*_interp_, Tcl\_Command _command_, Tcl\_Obj \*\*_subcmdListObjPtr_\) > > int **Tcl\_SetEnsembleSubcommandList**\(Tcl\_Interp \*_interp_, Tcl\_Command _command_, Tcl\_Obj \*_subcmdListObj_\) Tcl\_GetEnsembleMappingDict, Tcl\_SetEnsembleMappingDict: Read and write the dictionary that maps subcommands to prefixes of implementation commands. Equivalent to manipulating the **-map** option. > > int **Tcl\_GetEnsembleMappingDict**\(Tcl\_Interp \*_interp_, Tcl\_Command _command_, Tcl\_Obj \*\*_mapDictObjPtr_\) > > int **Tcl\_SetEnsembleMappingDict**\(Tcl\_Interp \*_interp_, Tcl\_Command _command_, Tcl\_Obj \*_mapDictObj_\) Tcl\_GetEnsembleUnknownHandler, Tcl\_SetEnsembleUnknownHandler: Read and write the command prefix list that is used to implement the unknown-subcommand handler. Equivalent to manipulating the **-unknown** option. > > int **Tcl\_GetEnsembleUnknownHandler**\(Tcl\_Interp \*_interp_, Tcl\_Command _command_, Tcl\_Obj \*\*_handlerListObjPtr_\) > > int **Tcl\_SetEnsembleUnknownHandler**\(Tcl\_Interp \*_interp_, Tcl\_Command _command_, Tcl\_Obj \*_handlerListObj_\) Tcl\_GetEnsembleFlags, Tcl\_SetEnsembleFlags: Read and write the flags for the ensemble. Currently there is only one settable flag bit, TCL\_ENSEMBLE\_PREFIX, which is present exactly when **-prefix** option is true. > > int **Tcl\_GetEnsembleFlags**\(Tcl\_Interp \*_interp_, Tcl\_Command _command_, int \*_flagsPtr_\) > > int **Tcl\_SetEnsembleFlags**\(Tcl\_Interp \*_interp_, Tcl\_Command _command_, int _flags_\) Tcl\_GetEnsembleNamespace: Reads the namespace associated with the ensemble; this value may not be altered. > > int **Tcl\_GetEnsembleNamespace**\(Tcl\_Interp \*_interp_, Tcl\_Command _command_, Tcl\_Namespace \*\*_namespacePtrPtr_\) ## Notes The handle for an ensemble is a normal Tcl\_Command handle, and any operation valid on such a command \(e.g. deleting it or finding its name\) is valid. Ensembles are just a special subclass of commands. This allows the ensemble API to be considerably sparser than it would otherwise have to be. # Reference Implementation The API is already in the core, but with internal naming and not exposed to anyone. Exposure is just renaming a few functions and putting them in the stubs table. No new types are exposed. All this means that a reference implementation is truly trivial. # Copyright This document has been placed in the public domain. |
Name change from tip/236.tip to tip/236.md.
|
| < | < | | | | | | | | > | | | | | | | | | | | | | | | > | 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 | # TIP 236: Absolute Positioning of Canvas Items Author: Neil McKay <[email protected]> State: Final Type: Project Vote: Done Created: 25-Dec-2004 Post-History: Keywords: Tk,anchor,place Tcl-Version: 8.6 ----- # Abstract This TIP proposes adding a canvas widget command to set the absolute position of canvas items. # Rationale There are many situations where it is desirable to move a group of canvas items to a given position. Currently, this is done by getting the items' first coordinate, calculating the offset required to move the items to the desired position, and using the canvas **move** command to translate the items to where we want them. This is tedious and inefficient. # The 'moveto' Canvas Command This TIP proposes adding a subcommand called **moveto** to the canvas widget command. It is analogous to the canvas **move** command, except that it accepts an absolute position instead of a relative displacement. For instance, the command .c moveto stuff 100 200 will displace all items tagged with _stuff_ so that the first coordinate of the first \(bottom-most\) tagged item lies at the point \(100,200\). The result of the command will be the empty string. ## Formal Syntax > _canvas_ **moveto** _tagOrId_ _x_ _y_ Argument description: canvas: The canvas instance's command. tagOrId: A specifier that selects one or more items. If no items are selected, the command does nothing. x, y: The absolute coordinates of the target location. If either coordinate is given as an empty string, then that coordinate will remain unchanged. # Patches A patch \(against tcl8.5a3\) that implements the **moveto** canvas subcommand is available <http://www.eecs.umich.edu/~mckay/canvmoveto.patch.gz> . # Copyright This document is in the public domain. |
Name change from tip/237.tip to tip/237.md.
|
| < | < | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 | # TIP 237: Arbitrary-Precision Integers for Tcl Author: Kevin B. Kenny <[email protected]> Author: Don Porter <[email protected]> State: Final Type: Project Vote: Done Created: 14-Jan-2005 Post-History: Tcl-Version: 8.5 ----- # Abstract This TIP adds the capability to perform computations on integer values of arbitrary precision. # Rationale There have been a number of issues in Tcl 8.4 dealing with the limited range of native integers and wide values. The original ideas of [[72]](72.md), while they have given at least the basics of 64-bit integer support, have also introduced some subtle violations of the doctrine that "everything is a string." Some of these have been insidious bugs - <http://sf.net/tracker/?func=detail&aid=868489&group_id=10894&atid=110894> and <http://sf.net/tracker/?func=detail&aid=1006626&group_id=10894&atid=110894> are illustrative - while others are perhaps not "bugs" in the strictest sense, but are still surprising behaviour. For instance, it is possible for a script to tell integers from wide integers even when their string representations are equal, by performing any arithmetic operation that overflows: % set x 2147483647 % set x [expr { wide(2146483647) }] 2147483647 2147483647 % incr x % incr x -2147483648 2147483648 With things as they stand, <http://sf.net/tracker/?func=detail&aid=1006626&group_id=10894&atid=110894> is nearly unfixable. It causes misconversion of large floating point numbers that look like integers: % set x -9223372036854775809 -9223372036854775809 % expr {double($x)} 9.22337203685e+018 % scan $x %g -9.22337203685e+018 The reason here is that the string of digits is first converted to a 64-bit unsigned integer \(**Tcl\_WideUInt**\). The '-' sign causes the unsigned integer to be interpreted as a signed integer, and the sign reversed. Since interpreting the unsigned integer as signed yields an overflow, the result is positive rather than negative and gives the odd behaviour shown above. Of course, even if the implementation of 64-bit arithmetic were bug free, there would be uses for arithmetic of higher precision. One example is that several Tcl users have attempted pure-Tcl implementations of RSA and Diffie-Hellman cryptographic algorithms. These algorithms depend on arithmetic of high precision; implementing them efficiently in today's Tcl requires a C extension because the high-precision algorithms implemented in Tcl are simply too slow to be acceptable. Finally, studying the references for accurate conversion of floating point numbers [[132]](132.md) reveals that input and output conversions both require arbitrary-precision arithmetic in their implementation. The reference implementation supplied with that TIP, alas, is code that is poorly commented and difficult to integrate into Tcl's build system. Reimplementing it according to Tcl's engineering practices means implementing a large part of an arbitrary-precision arithmetic library. # Proposal This TIP proposes augmenting Tcl with code for processing integers of arbitrary precision. Specifically: 1. The _libtommath_ library <http://math.libtomcrypt.com/> shall be added in a subdirectory of the Tcl source tree, parallel to _generic/_, _compat/_, etc. This library implements arithmetic on integers of arbitrary precision. For the rationale behind this library, and some of the precise integration details, see "Choice of Libary" below. 2. New functions, _Tcl\_NewBignumObj_, _Tcl\_SetBignumObj_, _Tcl\_GetBignumFromObj_ and _Tcl\_GetBignumAndClearObj_ shall be added to the Tcl library. They shall be specified as follows: > Tcl\_NewBignumObj: Creates an object containing an integer of arbitrary precision. The _value_ argument gives the integer in the format native to _libtommath_. _Upon return, the value argument is cleared, because its digit array has had its ownership transferred to the Tcl library._ > > Tcl\_Obj \***Tcl\_NewBignumObj**\(mp\_int \*_value_\) > Tcl\_SetBignumObj: Changes the value of an object to an integer of arbitrary precision. The _value_ argument gives the integer in the format native to _libtommath_. As with other **Tcl\_SetFooObj** routines, the **Tcl\_Obj** having its value set must be unshared \(copy on write\). As with **Tcl\_NewBignumObj**, the _value_ argument is cleared on return and the digit list is owned by Tcl thereafter. > > void **Tcl\_SetBignumObj**\(Tcl\_Obj \*_objPtr_, mp\_int \*_value_\) > Tcl\_GetBignumFromObj: Interprets an object as a large integer, and constructs a copy of that large integer in the _value_ argument. Returns _TCL\_OK_ if successful. On failure, stores an error message in the result of _interp_ and returns _TCL\_ERROR_. > > int **Tcl\_GetBignumFromObj**\(Tcl\_Interp \*_interp_, Tcl\_Obj\*_objPtr_, mp\_int \*_value_\) > Tcl\_GetBignumAndClearObj: Interprets an object as a large integer, and stores the large integer in the _value_ argument. Returns _TCL\_OK_ if successful. On failure, stores an error message in the result of _interp_ and returns _TCL\_ERROR_. Calls **Tcl\_Panic** if the object is shared. The object is reset to the empty state prior to return from this call. > > int **Tcl\_GetBignumAndClearObj**\(Tcl\_Interp \*_interp_, Tcl\_Obj\*_objPtr_, mp\_int \*_value_\) > The memory management of these routines deserves some explanation. For performance, it is desirable that copying bignums be avoided as far as possible. For this reason, the digit array stored in the _mp\_int_ object will be stored by pointer in the Tcl internal representation. This will result in memory problems unless the _mp\_int_ appears to be destroyed after it has been placed in a Tcl object, since further calls to the _libtommath_ functions may reallocate the array. > Similarly, when retrieving a large integer from an object, if the object retains an internal representation with the _mp\_int_, the _mp\_int_ must be copied. Code that intends to overwrite or destroy an unshared object immediately can avoid the copy by using the call that clears the object; this call returns the original _mp\_int_ without needing to do any memory management. 3. The _internalRep_ union in the _Tcl\_Obj_ structure shall be augmented with a _ptrAndLongRep_ field. This field shall be a structure comprising a pointer and a long integer. The pointer will designate an array of digits \(the _dp_ member of an _mp\_int_ structure in _libtommath_\). The long integer will be an encoding comprising: > \* one bit representing the sign of the number > \* fifteen bits giving the size of allocated memory in the digit array. > \* fifteen bits giving the size of used memory in the digit array. > The reason for this tight encoding is that the size of a _Tcl\_Obj_ shall not change, and yet an _mp\_int_ structure can be stored in the internal representation. This encoding will allow packing and unpacking the object with a few Boolean operations and shifts rather than needing to use a pointer internal representation and dynamically allocated memory to store the _mp\_int_. This packed representation is adequate to represent integers of \(2\*\*15 - 1\) _mp\_digit_s \(or 917,476 bits, since libtommath does its arithmetic in base 2\*\*28\). Since cryptographic algorithms, floating point conversions, and most number theoretic work will not exceed this length, the packed representation should cover nearly all values used in practice. > When an _mp\_int_ value too large for that tight packing is to be stored as the internal rep of a _Tcl\_Obj_, a copy of the _mp\_int_ value will be allocated from the heap, and a pointer to the copy stored in the pointer field. A value of **-1** in the long integer field will indicate this unpacked storage option. 4. A new _tclBignumType_ \(with type name **bignum**\) shall be added to the internal set of object types; it will have the _ptrAndLongRep_ internal representation, and the usual four conversion routines. 5. The _wideIntRep_ field in the _internalRep_ union shall remain \(lest there be extensions that use it\), but all code in the Tcl library that deals with it shall be removed. The routines, _Tcl\_GetWideIntFromObj_, _Tcl\_SetWideIntObj_, and _Tcl\_NewWideIntObj_ shall remain as part of the API, but will create objects with either _int_ or _bignum_ internal representations. 6. The **expr** command shall be reworked so that all integer arithmetic is performed _as if_ all integers are of arbitrary precision. In practice, numbers between LONG\_MIN and LONG\_MAX shall be stored in native long integers. The operators shall perform type promotions as needed. The command shall avoid \(as far as practicable\) performing arbitrary-precision arithmetic when native long ints are presented. Specifically: > \* Mixed mode arithmetic with floating point numbers shall work as it does today; the argument that is not a floating point number shall be converted. Note that it will be possible for conversion to overflow the floating-point arithmetic range; in this case, the value shall be replaced with _Inf_. > For arithmetic involving only integers: > \* The unary '-' operator shall promote LONG\_MIN to a mp\_int; this is the only input that can cause it to overflow. > \* The unary '\+' and '!' operators require no promotion; '\+' does nothing but verify that its argument is numeric, and '!' simply tests whether its argument is zero. > \* The binary '\*\*' operator \(and the _pow_ function\) shall promote to an arbitrary precision integer conservatively: when computing 'a\*\*b', it will precompute 'ceil\(log2\(a\)\*b\)', and promote if this logarithm exceeds LONG\_BITS-1. The result shall be demoted to an integer if it fits. > \* The binary '\*' operator, if either argument is an arbitary-precision integer, shall promote the other to an arbitrary-precision integer. If both are native integers, and _Tcl\_WideInt_ is at least twice the width of a native _long_, then the product will be computed in a _Tcl\_WideInt_, and the result will be either demoted to a _long_ \(if it fits\) or promoted to an _mp\_int_. > > In the case where _Tcl\_WideInt_ is not at least twice the width of _long_, the product will be computed to arbitrary precision and then demoted if it fits in a _long_. _This case is the only identified place where arbitrary-precision arithmetic will be used on native integers._ > \* The binary '/' operator, if either argument is an arbitrary-precision integer, shall promote the other. If the quotient fits in a _long_, it shall be demoted. > \* The binary '%' operator, in computing _a%b_, shall do the following: > > \* If _a_ and _b_ are both native long integers, the result is also a native long integer. > > \* If _a_ is a native long integer but _b_ is an arbitrary-precision integer, then _a<b_, and _a%b_ can be computed without division. > > \* If _b_ is a native _long_, the division will be carried out using the arbitrary precision library, but the result will always be a native _long._ > > \* If _a_ and _b_ are both arbitrary-precision integers, the result will be computed to arbitrary precision, but demoted if it fits in a _long_. > \* The binary _\+_ and _-_ operators, if either operand is an arbitrary-precision integer, shall promote the other operand to an arbitrary-precision integer, compute the result to arbitrary precision, and demote the result to _long_ if it fits. If both operands are native _long_, and _Tcl\_WideInt_ is larger than a native _long_, then the result will be computed to _Tcl\_WideInt_ precision, and demoted to _long_ if it fits. > > In the case where _Tcl\_WideInt_ is only as wide as _long_, the operators shall test for overflow when adding numbers of like sign or subtracting numbers of opposite sign. If the sign of the result of one of these operations differs from the sign of the first operand, overflow has occurred; the result is promoted to an arbitrary precision integer and the sign is restored. > \* The _<<_ operator shall fail if its second operand is an arbitrary-precision integer and the first is nonzero \(because this case must exceed the allowable number of digits\). It returns an arbitrary-precision integer if its first argument is an arbitrary-precision integer, or if the shift will overflow. The overflow check for _long_ values \(_a<<b_\) is > > \* if _b_>LONG\_BITS-1, overflow. > > \* if _a_>0, and \(a & -\(1<<\(LONG\_BITS-1-b\)\)\), overflow. > > \* if _a_<0, and \(~a & -\(1<<LONG\_BITS-1-b\)\)\), overflow. > \* The '>>' operator _a>>b_, shall return 0 \(_a>=0_\) or -1 \(_a<0_\) if _b_ is an arbitrary-precision integer \(it would have shifted away all significant bits\). Otherwise, the shift shall be performed to the precision of _a_, and if _a_ was an arbitrary-precision integer, the result shall be demoted to a _long_ if it fits. > \* The six comparison operators <, <=, ==, !=, >=, and >, can work knowing only the signs of the operands wben native _long_ values are compared with arbitrary-precision integers. Arbitrary-precision comparison is needed only when comparing arbitrary-precision integers of like sign. In any case, the result is a native _long_. > \* The _eq_, _ne_, _in_, and _ni_ operators work only on string representations and will not change. > \* The _&&_ and _\|\|_ and _?:_ operators only test their operands for zero and will not change. > \* The ~ operator shall follow the algebraic identity: > > ~a == -a - 1 > > This identity holds if _a_ is represented in any word size large enough to hold it without overflowing. It therefore generalizes to integers of arbitary precision; essentially, negative numbers are thought of as "twos-complement numbers with an infinite number of 1 bits at the most significant end." > \* The base case of the _&_ \(_a&b_\) operator shall be defined in the obvious way if _a_ and _b_ are both positive; corresponding bits of their binary representation will be ANDed together. For negative operands, the algebraic identity above, together with De Morgan's laws, can reduce the operation to the base case: > > \* if a>=0, b<0, a&b == a & ~\( ~b \) == a & \( - b - 1 \) > > \* if a<0, b>=0, symmetric with the above. > > \* if a<0, b<0, a & b = ~\( ~a \| ~b \) = -\( \( -a - 1 \) \| \( -b - 1 \) \) - 1 > \* The base case of the _\|_ \(_a\|b_\) operator shall be defined in the obvious way if _a_ and _b_ are both positive: corresponding bits of their binary representation will be ORed together. For negative operands, the algebraic identity above, together with De Morgan's laws, can reduce the operation to the base case: > > \* if a>=0, b<0, a\|b == ~\( ~a & ~b \) == -\( ~a & \( -b - 1 \)\) - 1 > > \* if a<0, b>=0, symmetric with the above. > > \* if a<0, b<0, a\|b == ~\( ~a & ~b \) == -\( \( -a - 1 \) & \( -b - 1 \) \) - 1 > \* The base case of the _^_ \(_a^b_\) operator shall be defined in the obvious way if _a_ and _b_ are both positive: corresponding bits of their binary representation will be EXCLUSIVE ORed together. For negative operands, the algebraic identity above, together with the contrapositive law, can reduce the operation to the base case: > > \* if a>=0, b<0, a^b == ~\( a ^ ~b \) == -\( a ^ \( -b - 1 \) \) - 1 > > \* if a<0, b>=0, symmetric with the above. > > \* if a<0, b<0, a^b == ~a ^ ~b == \( -a - 1 \) ^ \( -b - 1 \) > \* The abs\(\), ceil\(\), double\(\), floor\(\), int\(\), round\(\), sqrt\(\), and wide\(\) math functions shall all be modified to accept arbitrary-precision integers as parameters. All these functions will continue to return the same "type" as they do now \(integer vs. floating point\), but the domain and/or range will be extended to permit arbitrarily large integers as appropriate. > \* A new function, _entier\($x\)_ will be introduced; the function coerces _$x_ to an integer of appropriate size. _entier\(\)_ is distinguished from _int\(\)_ in that _int\(\)_ results in an integer limited to the size of the native long integer always, while _entier\(\)_ results in whatever size of integer is needed to hold the full value. 7. The **incr** and **dict incr** commands shall work on arbitary-precision values. Specifically, [incr a $n] will behave like [set a [expr { $a + $n }]] with the constraint that _$a_ and _$b_ must both be integers. 8. The **format** and **scan** commands will acquire _%lld_, _%lli_, _%llo_, _%llx_ and _%llX_ specifiers that format their arguments as arbitrary-precision decimal, \(decimal/any format\), octal, and hexadecimal integers, respectively. The format specifier _%llu_ is invalid and will cause an error. The _%llo_ and _%llx_ specifiers, unlike their native-integer counterparts, will format _signed_ numbers; the result of [format %#llx -12345] will not be 0xffffcfc7, but rather -0x3039. \(If an application requires hexadecimal numbers in two's complement notation, it can get them by forcing a number to be positive: set x -12345 set x64bit [expr { $x & ((1<<64) - 1) }] format %#llx $x64bit > will yield '0xffffffffffffcfc7'. 9. User defined math functions will be able to gain access to a _bignumValue_ only if they are created using the techniques described in [[232]](232.md). The Tcl command that implements the user defined math function will be able to receive a **bignum** Tcl\_Obj value just as it can receive any other Tcl\_ObjType. The legacy _Tcl\_Value_ structure, will **not** be updated to add a bignum-valued field. 10. The number parser detailed in [[249]](249.md) will be adopted into the Tcl internals. See [[249]](249.md) for details on the implications. # Integration Details The _libtommath_ source code shall be extracted from the distributions available at <http://math.libtomcrypt.com/> and brought into the CVS repository as a _vendor branch_ \(see <https://www.cvshome.org/docs/manual/cvs-1.11.18/cvs_13.html#SEC103> for a discussion of managing vendor branches. It appears that all the necessary modifications to integrate this source code with Tcl can be made in the single file, _tommath.h_; it is likely that the _tools/_ directory in the Tcl source tree will contain a Tcl script to make the modifications automatically when importing a new version. CVS can maintain local modifications effectively, should we find it necessary to patch the other sources. The chief modification is that all the external symbols in the library will have TclBN prepended to their names, so that they will not give linking conflicts if an extension uses a 'tommath' library not supplied with Tcl - or uses any other library compatible with the Berkeley _mp_ API. # Choice of Library The _libtommath_ code is chosen from among a fairly large set of possible third-party bignum codes. Among the ones considered were: GMP: The Gnu GMP library is probably the fastest and most complete of the codes available. Alas, it is licensed under LGPL, which would require all distributors who prepare binary Tcl distributions to include the GMP source code. I chose to avoid any legal entanglements, and avoided GMP for this reason. The original Berkeley mp library: This library is atrociously slow, and was avoided for that reason. Gnu Calc: GPL licensed. A non-starter for that reason. mpexpr: This Tcl extension has been available for many years and is released under the BSD license. \(It was the basis for Gnu Calc but predates the fork, and hence is not GPL-contaminated.\) It would certainly be a possibility, but the code is not terribly well documented, is slow by today's standards, and still uses string-based Tcl API's. It would be a considerable amount of work to bring it into conformance with today's Tcl core engineering practices. OpenSSL: The OpenSSL library includes a fast and well-documented bignum library \(developed so that OpenSSL can do RSA cryptography\). Alas, the code is licensed under the original BSD license agreement, and has several parties added to the dreaded Advertising Clause. The Advertising Clause would present serious difficulties for our distributors, and so OpenSSL is not suitable. \(The OpenSSL developers are not amenable to removing the Advertising Clause from the license.\) Several libraries implemented in C\+\+ were dismissed out of hand, because of the deployment issues associated with C\+\+ runtime libraries and static constructors. The _libtommath_ code is released to the Public Domain. Its author, Tom St. Denis, explicitly and irrevocably authorizes its use for any purpose, without fee, and without attribution. So license incompatibilities aren't going to be an issue. The documentation is wonderful \(Tom has written a book of several hundred pages <http://book.libtomcrypt.com/draft/tommath.pdf> describing the algorithms used\), and the code is lucid. The chief disadvantage to _libtommath_ is that it is a one-person effort, and hence has the risk of becoming orphaned. I consider this risk to be of acceptable severity, because of the quality of the code. The Tcl maintainers could take it on quite readily. # Additional Possibilities The Tcl library will actually use only about one-third of _libtommath_ to implement the _expr_ command. In particular, the library functions for squaring, fast modular reduction, modular exponentiation, greatest common divisor, least common multiple, Jacobi symbol, modular inverse, primality testing and the solution of linear Diophantine equations are not needed, and shall not be include in the Tcl library to save memory footprint. Nevertheless, these operations would be extremely useful in an extension, so that programs that don't live with tight memory constraints can do things like fast Diffie-Hellman or RSA cryptography. We should probably consider a 'bignum' package to be bundled with the core distribution that would add appropriate math functions wrapping these operations. # Reference Implementation A feature complete implementation is present on the CVS branch called 'kennykb-numerics-branch'. # Copyright Copyright © 2005 by Kevin B. Kenny. All rights reserved. This document may be distributed subject to the terms and conditions set forth in the Open Publication License, version 1.0 <http://www.opencontent.org/openpub/> . |
Name change from tip/238.tip to tip/238.md.
|
| < | < | | | | | | | | > | | | | | | | | | | < > | | | | | | > | 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 | # TIP 238: Fire Event when Widget Created Author: Gerald W. Lester <[email protected]> State: Draft Type: Project Vote: Pending Tcl-Version: 8.7 Created: 25-Jan-2005 Post-History: Keywords: Tk ----- # Abstract This TIP arranged for a new virtual event to be fired every time a widget is created. This allows class bindings to automatically discover new widget instances and act on their creation. # Rationale It would be useful if it was possible to set an event on class bindings to allow custom code to be run when a widget of a particular class is created. Note that the standard X11 <Create> event is not quite suitable, because that is delivered to the X11 parent of the widget, which is not Tk in the case of toplevel windows. # Proposal It is proposed that the virtual event <<Create>> be sent to every widget upon the creation of its actual underlying window \(i.e. as part of **Tk\_MakeWindowExist**\). Note that this is the earliest at which an event can actually be delivered to the widget; before that, doing **event generate** to the widget just creates an event that gets discarded. ## Example % bind Toplevel <<Create>> { puts stdout {New toplevel called {%W} was created!} } % toplevel .foo New toplevel called {.foo} was created! ## Proposed C API Changes No changes would be requried, this change is for the Tcl layer API. # Reference Implementation A reference implementation does _not_ yet exist. # Copyright This document has been placed in the public domain. |
Name change from tip/239.tip to tip/239.md.
|
| < | < | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | < > | | | | | > | 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 | # TIP 239: Enhance the 'load' Command Author: Jeff Hobbs <[email protected]> State: Draft Type: Project Vote: Pending Created: 26-Jan-2005 Post-History: Tcl-Version: 8.7 ----- # Abstract This TIP proposes enhancing the Tcl **load** command with the ability to load arbitrary libraries and functions. # Rationale The current Tcl **load** command limits itself operating within the context of loading Tcl extension libraries and nothing else, even though all the code is there for general library loading. With the introduction of the VFS and more extensions having prerequisite library dependencies, the ability to load arbitrary libraries would ease development of StarKits with these extensions. It will also provide a general mechanism to assist other developers get around the difficult process of cross-platform library loading. # Specification Current specification: > **load** _fileName_ ?_packageName_ ?_interp_?? Recommended specification: > **load** ?**-function** _funcName_? ?**-interp** _interp_? ?**-package** _packageName_? ?**-keeplibrary**? ?**--**? _fileName\|\|libref_ > returns library pointer reference value The **-interp** option takes the place of the optional final _interp_ argument. The **-package** option replaces the optional _packageName_ argument. The user specifies just the partial function name without the "\_Init" or "\_SafeInit", as before. The function is called with the Tcl interpreter to initialize as the sole argument. If this option is not specified, the name is inferred from the filename. If **-function** is specified, the Init call is not made. The **-function** option takes a C function name to find the symbol of \(via dlsym\(\), GetProcAddress\(\), or related function\). If **-function** is specified, **-call** and **-interp** are ignored and the return value is the pointer location to the function, or 0 if it is not found. When this is used, the library is not closed upon success, it remains open until a call to **unload** is made. The **-keeplibrary** option set a flag to indicate the library should not be unloaded by Tcl. This is needed in cases where the library may register functions \(eg, via C's **atexit**\) that are needed beyond the lifetime of Tcl finalization. This should only be used when necessary. An error is thrown if the library cannot be loaded, otherwise a library pointer reference value is returned \(unless **-function** is used\). **load** could take a library pointer reference as an argument for repeated **-function** requests. I will also recommend obsoleting the existing **unload** call to use this new functional spec style. Current spec, to be unsupported \(it's new in 8.5\): > **unload** ?_switches_? _fileName_ ?_packageName_ ?_interp_?? New specification: > **unload** ?**-interp** _interp_? ?**-package** _packageName_? ?**-keeplibrary**? ?**--**? _fileName\|\|libref_ I removed the _-nocomplain_ option. The user should simply **catch** the command if they wish to suppress the types of errors that unload would throw. I think that C functions should be made available as well for cross-platform access to the load functionality, but that is not specified in this TIP. This would need to account for users that may configure Tcl with --disable-load \(does anybody need that anymore?\). # Discussion Not all platforms may support library loading to a degree required for this TIP functionality. In that case, an error message will be thrown. The use of **--** as a option end switch was debated as unnecessary since there is only one fixed argument. JH likes the use of it for the completeness it gives the use of switches. The **load** command will determine the use of the new form by checking if more than one argument is given and the first argument starts with a **-**. This should not affect any existing extensions, as dynamic library filenames beginning with **-** are rare. Here is a reference to Perl's dynamic library loading functionality: <http://aspn.activestate.com/ASPN/Perl/Products/ActivePerl/5.8/lib/DynaLoader.html> # Examples For a package in a starkit, tls example with shared OpenSSL library shipped in package: # $dir set by package mechanism if {[package provide starkit] ne ""} { load -call {} $dir/libopenssl.so } load $dir/libtls1.5.so This would handle the extracting of dependent libraries in starkits automatically \(and their subsequent disposal\). Another example would be Oratcl 4.3's use of dynamic Oracle library callouts, which it has to do by hand due to the lack of this functionality in the core. # Reference Implementation [To be uploaded to SourceForge and URL added to this TIP.] # Copyright This document has been placed in the public domain. |
Name change from tip/24.tip to tip/24.md.
|
| < | < | | | | | | | | | | | | > | | | | | | | | | | | | | | < < | < < | | | | | | | | | | < > > > > > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 24: Tcl Maintainer Assignments Author: Don Porter <[email protected]> Author: Donal K. Fellows <[email protected]> Author: Kevin B. Kenny <[email protected]> Author: Jeff Hobbs <[email protected]> Author: Pavel Goran <[email protected]> Author: Daniel A. Steffen <[email protected]> Author: miguel sofer <[email protected]> State: Draft Type: Informative Vote: Pending Created: 29-Jan-2001 Post-History: ----- # Abstract This document keeps a record of who maintains each functional area of Tcl \([[16]](16.md)\). # Assignments Listed below are Tcl's functional units, in the same order as in [[16]](16.md). See [[16]](16.md) for the precise definition of what code belongs to what area. The area names are changed to match the Categories in Tcl's SourceForge Bug Manager <http://sourceforge.net/bugs/?group_id=10894> . Note that an area can have more than one maintainer. When the maintenance of the entire area requires several types of expertise, it is desirable to have more than one maintainer. In several of the areas below, there are maintainers who have volunteered to provide special expertise \(for example, assistance with programming and testing for the Mac platform\) to assist in maintaining an area, but who have not taken on the whole area. These maintainers are indicated by a parenthesized designation of their expertise. For each of Tcl's functional units, the following maintainers are assigned: 1. _Notifier_ - Kevin Kenny <[email protected]> \(Win32, Solaris, HP-UX\), Daniel Steffen <[email protected]> \(Mac OS X\), Alexandre Ferrieux <[email protected]> 1. _Event Loops_ - Jan Nijtmans <[email protected]>, Jeff Hobbs <[email protected]> 1. _Timer Events_ - Kevin Kenny <[email protected]>, Jeff Hobbs <[email protected]> 1. _Async Events_ - Joe Mistachkin <[email protected]> 1. _XT Notifier_ - 1. _Time Measurement_ - Kevin Kenny <[email protected]>, Jeff Hobbs <[email protected]> 1. _Variables_ - Miguel Sofer <[email protected]>, Jeff Hobbs <[email protected]> 1. _Environment Variables_ - Jeff Hobbs <[email protected]> 1. _Linked C Variables_ - Jeff Hobbs <[email protected]> 1. _Objects_ - Miguel Sofer <msofer@users.sf.net>, Alexandre Ferrieux <[email protected]>, Jeff Hobbs <[email protected]> 1. _Conversions from String_ - Jeff Hobbs <[email protected]> 1. _ByteArray Objects_ - Donal K. Fellows <[email protected]>, Jan Nijtmans <[email protected]>, Alexandre Ferrieux <[email protected]>, Jeff Hobbs <[email protected]> 1. _Index Object_ - Jan Nijtmans <j.nijtmans@chello.nl>, Jeff Hobbs <JeffH@ActiveState.com> 1. _List Object_ - Jan Nijtmans <j.nijtmans@chello.nl>, Jeff Hobbs <[email protected]> 1. _Dict Object_ - Donal K. Fellows <[email protected]> 1. _Commands A-H_ - Donal K. Fellows <[email protected]>, Jeff Hobbs <[email protected]> 1. _Commands I-L_ - Donal K. Fellows <[email protected]>, Jeff Hobbs <[email protected]> 1. _Commands M-Z_ - Donal K. Fellows <dkf@users.sf.net>, Jeff Hobbs <[email protected]> 1. _[history]_ - Jeff Hobbs <[email protected]> 1. _[interp]_ - Jeff Hobbs <[email protected]> 1. _[namespace]_ - Miguel Sofer <[email protected]>, Jeff Hobbs <[email protected]>, Donal K. Fellows <[email protected]> \(especially ensembles\) 1. _[proc] and [uplevel]_ - Miguel Sofer <[email protected]>, Jeff Hobbs <[email protected]> 1. _[scan]_ - Jeff Hobbs <[email protected]> 1. _Channel Commands_ - Andreas Kupries <[email protected]>, Jeff Hobbs <[email protected]> 1. _Channel System_ - Andreas Kupries <[email protected]>, Alexandre Ferrieux <[email protected]>, Jeff Hobbs <[email protected]> 1. _Channel Transforms_ - Andreas Kupries <[email protected]>, Jeff Hobbs <[email protected]> 1. _Channel Types_ - Andreas Kupries <[email protected]>, Rolf Schroedter <[email protected]> \(WinSerial\), Jeff Hobbs <[email protected]> 1. _dde Package_ - Pat Thoyts <[email protected]>, Kevin Kenny <[email protected]> 1. _http Package_ - Pat Thoyts <[email protected]>, Jeff Hobbs <[email protected]> 1. _msgcat Package_ - Harald Oehlmann <[email protected]> 1. _opt Package_ - Jan Nijtmans <[email protected]> 1. _registry Package_ - Kevin Kenny <[email protected]> 1. _Safe Base_ - Jeff Hobbs <[email protected]> 1. _tcltest Package_ - Jeff Hobbs <[email protected]>, Melissa Chawla <[email protected]>, Don Porter <[email protected]> 1. _TclOO Package_ - Donal K. Fellows <[email protected]> 1. _Pathname Management_ - Vincent Darley <[email protected]>, Jeff Hobbs <[email protected]> 1. _File System_ - Vincent Darley <[email protected]>, Jeff Hobbs <[email protected]>, Daniel Steffen <[email protected]> \(Mac OS X\), Jim Ingham <[email protected]> \(Mac OS X\) 1. _Init - Library - Autoload_ - Don Porter <[email protected]>, Jeff Hobbs <[email protected]>, Daniel Steffen <[email protected]> \(Mac OS X\), Jim Ingham <[email protected]> \(Mac OS X\) 1. _Package Manager_ - Don Porter <[email protected]>, Jeff Hobbs <[email protected]> 1. _Dynamic Loading_ - Kevin Kenny <[email protected]>, Jan Nijtmans <[email protected]>, Jeff Hobbs <[email protected]>, Daniel Steffen <[email protected]> \(Mac OS X\), Jim Ingham <[email protected]> \(Mac OS X\) 1. _Memory Allocation_ - Jeff Hobbs <[email protected]>, Joe Mistachkin <[email protected]> 1. _Memory Preservation_ - Jeff Hobbs <[email protected]> 1. _Regexp_ - Pavel Goran <[email protected]>, Colin McCormack <[email protected]> 1. _UTF-8 Strings_ - Jan Nijtmans <[email protected]>, Jeff Hobbs <[email protected]> 1. _Parsing and Eval_ - Miguel Sofer <[email protected]>, Jeff Hobbs <[email protected]>, Don Porter <[email protected]> 1. _Traces_ - Don Porter <[email protected]> 1. _Bytecode Compiler_ - Miguel Sofer <[email protected]>, Jeff Hobbs <[email protected]> 1. _Number Handling_ - Don Porter <[email protected]>, Kevin Kenny <[email protected]> 1. _Threading_ - Andreas Kupries <[email protected]>, Jeff Hobbs <[email protected]>, Joe Mistachkin <[email protected]> 1. _Embedding Support_ - Don Porter <[email protected]>, Jeff Hobbs <[email protected]>, Joe Mistachkin <[email protected]> 1. _Release Notes_ - Don Porter <[email protected]>, Jeff Hobbs <[email protected]>, Daniel Steffen <[email protected]> \(Mac OS X\), Jim Ingham <[email protected]> \(Mac OS X\) 1. _Portability Support_ - Mo DeJong <[email protected]>, Jeff Hobbs <[email protected]>, Zoran Vasiljevic <[email protected]> 1. _Configure and Build Tools_ - Mo DeJong <[email protected]>, Jeff Hobbs <[email protected]>, Lloyd Lim <[email protected]>, Acacio Cruz <[email protected]> \(BSD\), Daniel Steffen <[email protected]> \(Mac OS X\), Jim Ingham <[email protected]> \(Mac OS X\), Pat Thoyts <[email protected]> \(Windows\) 1. _Configuration Reporting_ - Andreas Kupries <[email protected]> 1. _Other Tools_ - Jeff Hobbs <[email protected]> 1. _LibTomMath_ - Kevin Kenny <[email protected]> 1. _zlib_ - Donal K. Fellows <[email protected]> # Orphaned Categories The following Categories in Tcl's SourceForge Bug Tracker should be mapped to new Categories corresponding to a maintained area of Tcl, when seeking the appropriate maintainer: 67. _[resource] \(obsolete\)_ - Used for closed old reports about the **resource** command that was implemented only on the now unsupported Mac Classic platform. 68. _Mac Classic \(obsolete\)_ - Used for closed old reports about other issues on the now unsupported Mac Classic platform. 69. _Other_ - Used for reports that span several categories. Also includes many closed old reports from before the time the current categories were established. # Sections Without Maintainers Those sections without a maintainer are maintained by the Tcl Core Team with each change requiring TYANNOTT review. # Copyright This document has been placed in the public domain. |
Name change from tip/240.tip to tip/240.md.
|
| < | < | | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | < < < > > > | | | | | | | | | < > | | < < > > | | | | | | | | | | | | | | | | | < > | | | | | | | < > | | | | < > | | | < > | | | < < > > | < > | | | | | | | | | | < < > > | | | | | | | | | | | < < > > | | | | | | < > | | | < > | | | | | < > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 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 | # TIP 240: An Ensemble Command to Manage Processes Author: Steve Bold <[email protected]> State: Draft Type: Project Vote: Pending Created: 22-Feb-2005 Post-History: Keywords: Tcl Obsoletes: 88 Tcl-Version: 8.7 ----- # Abstract This TIP proposes some new commands through which Tcl scripts can create and monitor child processes. # Rationale This TIP is intended to overcome the following limitations of the existing **exec** and **open** commands: 1. While the stderr stream of a child process can be redirected to a file, it cannot be directed to a pipe and so cannot be captured progressively as the process runs. [[202]](202.md) has partially addressed this issue but only for the case where the child's stderr stream is directed to the same pipe as its stdout stream. Independent progressive capture of both stdout and stderr is still not possible. 2. In the \(admittedly rare\) case that a program has a significant delay between closing its standard streams and the process itself terminating, a Tcl script running that program as a background process cannot determine the exit status without blocking until the process terminates. 3. The existing **exec** and **open** commands impose a special interpretation on the characters _<>\|&_. This causes two kinds of problems: > \* scripts wishing to invoke a command on a remote computer using an _rsh_ or similar command will sometimes wish to have characters such as _<>\|&_ interpreted on the remote machine > \* scripts may pass a user entered string as an argument to exec. Such scripts may break unexpectedly if the comment string contains one of the special characters. Such problems could be considered a security weakness in Tcl. 4. Multiple child processes can be launched together with pipes used to link the streams of adjacent processes. However, little flexibility is provided in such cases, for example you can only capture the exit status of the last process in the pipeline. A more general problem is that each process related command is a separate top-level command. This is inconsistent with much else in Tcl, makes it harder to find the related commands in some forms of documentation and increases the risk of name clashes as new process related commands are introduced. The BLT toolkit contains the command **bgexec** which addresses items \(1\) and \(2\) in the above list. However, the resulting implementation is complex and does not appear easy to transfer to the Tcl core. In addition, it is not clear to the author how **bgexec** could be extended to address items \(3\) and \(4\). A variety of other approaches to addressing these problems are listed on the Wiki <http://wiki.tcl.tk/1353> . This suggests that it may be difficult to achieve a consensus on what the ideal command\(s\) for launching processes should look like. This TIP provides a basis through which many of these approaches could be implemented in pure Tcl. The commands specified in this TIP map easily onto the existing low level process related functions in the Tcl core, so the implementation cost is low. # Specification There shall be a new ensemble command, **process**, with at least four subcommands. 1. The sub-command **invoke** takes 4 arguments and invokes a sub-process, returning the process id of the child process. The arguments are \(in order\): > \* a list containing the program name invoke and its arguments > \* a channel to be connected to the stdin stream of the child process \(or an empty string if the channel is to be disconnected in the child process\). > \* a channel to be connected to the stdout stream of the child process \(or an empty string if the channel is to be disconnected in the child process\). > \* a channel to be connected to the stderr stream of the child process \(or an empty string if the channel is to be disconnected in the child process\). 2. The sub-command **pipe** takes no arguments and returns a two element list containing the input and output channels of the pipe in that order. 3. The sub-command **status** takes a single argument which is a process id and returns a two element list. The first element is either _running_ or _completed_ The second element is the exit status of the process. > A process will report an arbitrary exit status of zero while it is running. 4. The sub-command **wait** is similar to **status** but blocks until the child process has completed. # Examples The following shows how the commands proposed here can be used to produce a **bgexec** like command in pure Tcl. Not all the **bgexec** options are included and the implementation lacks the error handling needed for a robust implementation. proc bgExecCloseHandler {pid cmd} { lassign [process status $pid] status exitCode if {$status eq "running"} { puts "... deferring close handling for $pid" after 1000 [list bgExecCloseHandler $pid $cmd] } else { if {$cmd ne ""} { {expand}$cmd $pid $exitCode } } } proc bgExecReadHandler {chan cmd} { if {[gets $chan line] == -1} { close $chan if {[info exists ::bgExecCloseInfo($chan)]} { lassign $::bgExecCloseInfo($chan) pid cmd after 0 bgExecCloseHandler $pid $cmd unset ::bgExecCloseInfo($chan) } } else { {expand}$cmd $line } } proc bgExecLike {args} { set outChan ""; set errChan "" set i 0 set exitCmd ""; set parentOutChan "" while {$i != [llength $args]} { set arg [lindex $args $i] switch -glob -- $arg { -onoutput { incr i set cmd [lindex $args $i] lassign [process pipe] parentChan outChan fileevent $parentChan readable [list \ bgExecReadHandler $parentChan $cmd] set outCmd $cmd set parentOutChan $parentChan } -onerror { incr i set cmd [lindex $args $i] lassign [process pipe] parentChan errChan fileevent $parentChan readable [list \ bgExecReadHandler $parentChan $cmd] } -onexit { incr i set exitCmd [lindex $args $i] } -* { error "Unknown switch $arg" } * { break } } incr i } set cmdLine [lrange $args $i end] # puts [list process invoke $cmdLine "" $outChan $errChan] set pid [process invoke $cmdLine "" $outChan $errChan] # Close the child end of the pipes - if we opened them. foreach var {outChan errChan} { if {[set $var] ne ""} { close [set $var] } } if {$parentOutChan eq ""} { # Poll for child process exit then notify client, or at least # clean up the zombie. after 0 bgExecCloseHandler $pid $exitCmd } else { # We copy BLT's trick of deferring polling till the stdout pipe # closes. This is marginally more efficient, more importantly # it stops clients being notified of their process until at stdout # channel has closed. set ::bgExecCloseInfo($parentOutChan) [list $pid $exitCmd] } } # now show bgExecLike in action ... proc showExit {pid code} { puts "$pid terminated with code $code" } proc showLine {channel line} { puts "$channel: $line" } proc runLs {args} { puts "invoking ls on $args" bgExecLike -onoutput "showLine stdout" -onerror "showLine stderr" \ -onexit showExit ls {expand}$args } # Sample invocations: note when running under tclsh, there is no event loop, # use 'update' to see the output to see what's happening. # successful listing runLs . # Unsuccessful listing runLs not-found # Listing of (non existent) files containing exec/open meta characters runLs < > | & # Limitations 1. For convenient use, the functionality proposed here needs to be supplemented with additional commands providing a higher level interface, perhaps one of them being similar to the **bgExecLike** example given previously. The author has decided to omit this feature from the TIP because: > \* such commands can be implemented in pure Tcl using the commands described here > \* the exact nature of the high level commands may produce lengthy discussions > \* it could even be argued that such commands are more appropriate in tcllib rather than the Tcl core 2. As with the current implementation of **exec**, each channel passed to **process invoke** must have a valid underlying OS file handle. Consequently when running on Windows: > \* use of a wish standard channel will be immediately rejected > \* use of a socket will be accepted but will trigger an error in the child process. 3. Efficiency - The author has not yet attempted a detailed performance study, but this proposal does have some theoretical inefficiencies when compared to a pure C implementation, such as **bgexec**: > \* an intermediate Tcl procedure is used to capture output from a pipe > \* each end of each pipe has to be wrapped in a _CommandChannel_ before it can be passed back to the calling script, even if the pipe is just going to be used to link together two processes in a pipeline. # Related Possibilities for Future Enhancements 1. For Windows, an important limitation that is not addressed by this TIP, is the lack of control over the console window settings when invoking a process. This will require changes to _TclpCreateProcess_. 2. A **kill** subcommand would be a useful addition to the **process** ensemble. On Windows, the ability to kill a child console process cleanly is related to the choice of console mode, so this issue would ideally be addressed in conjunction with item \(1\) above. 3. A command to categorise an exit status obtained from **process status** or **process wait** along similar lines to the data placed in _$errorCode_ by _TclCleanupChildren\(\)_. 4. Some aspects of the existing **exec** command depend on use of temporary files. Since this TIP transfers the high level implementation of process launching into Tcl scripts, support for creation of uniquely named temporary files, as proposed in [[210]](210.md), would be useful. 5. The wish console on Windows could be improved, using this mechanism, so that program names typed interactively will run in the background, allowing output to be seen before the process completes. 6. The ability to define _argv[[0]](0.md)_, independently from the program name, would occasionally be useful. For example, some UNIX shells run as login shells when _argv[[0]](0.md)_ begins with a dash. 7. Public C functions for invoking a process and creating a pipe wrapped in command channels. 8. Support for detaching process and for reaping detached processes. 9. The existing **exit** command could be duplicated in the **process** ensemble. 10. The basic form of the existing **pid** command, which obtains the process id of the current process, could be added to the **process** ensemble. 11. In some cases, it is more appropriate to run a child process with its streams connected to a null file rather than disconnected. Since the name of the null file is platform specific, it would be helpful to have a platform independent way of accessing the name. 12. An option to obtain full status information. On Windows, process exit codes are 32 bit. On UNIX, higher bits of a waitpid\(\) status value distinguish termination via exit\(\) from termination via an uncaught signal. # Reference Implementation Submitted as patch 1315115 <https://sourceforge.net/support/tracker.php?aid=1315115> # Copyright This document has been placed in the public domain. |
Name change from tip/241.tip to tip/241.md.
|
| < | < | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 241: Case-Insensitive Switches and List Searching and Sorting Author: Joe Mistachkin <[email protected]> State: Final Type: Project Vote: Done Created: 26-Feb-2005 Post-History: Keywords: Tcl,sorted lists,matching Tcl-Version: 8.5 ----- # Abstract This TIP proposes a **-nocase** option for the **lsearch**, **lsort** and **switch** commands to allow for case-insensitive handling of the specified list. # Rationale The **lsearch**, **lsort** and **switch** commands are very flexible and powerful. However, in certain situations the ability to perform case-insensitive searching and sorting is absolutely required \(such as searching fully qualified file names on file systems that do not differentiate between upper and lower case\). Without the **-nocase** option, various unnatural workarounds are required. In addition, the **-nocase** option will finally bring the **lsearch** command into parity with the other comparison related operations, including **string compare**, **string match**, and **regexp**. # Specification Options will be added like this: > **lsearch** ?**-nocase**? _list_ _pattern_ > **lsort** ?**-nocase**? _list_ > **switch** ?**-nocase**? _string bodyDefinition_ For **lsearch**, the **-nocase** option can be used with the **-ascii**, **-exact**, **-glob**, and **-regexp** options. It indicates that the string of the found entry of _list_ should match _pattern_ case-insensitively. It is compatible with the **-all**, **-decreasing**, **-increasing**, **-inline**, **-not** and **-start** options. For **lsort**, the **-nocase** option can be used with the **-ascii** option. It indicates that the list should be sorted based on a case-insensitive ordering. It is compatible with the **-decreasing**, **-increasing**, **-index** and **-unique** options. For both **lsearch** and **lsort**, the **-nocase** option has no effect when used with the **-dictionary**, **-integer**, or **-real** options. For **lsort**, the **-nocase** option has no effect when used with the **-command** option. For **switch**, the **-nocase** option can be used with all three matching modes \(**-exact**, **-glob**, **-regexp**\) and indicates that the matching of _string_ should be performed in a case-insensitive manner. # Reference Implementation A reference implementation of this TIP is available <http://sourceforge.net/tracker/index.php?func=detail&aid=1152746&group_id=10894&atid=310894> . # Copyright This document has been placed in the public domain. |
Name change from tip/242.tip to tip/242.md.
|
| < | < | | | | | | | > | | | | | | | | | | | | | | | < > | | | | | | | | | | | | > | 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 | # TIP 242: Preselect Filter on tk_get*File Dialogs Author: Brian Griffin <[email protected]> State: Final Type: Project Vote: Done Created: 03-Mar-2005 Post-History: Tcl-Version: 8.5 ----- # Abstract This TIP proposes adding an **-typevariable** option to the **tk\_getOpenFile** and **tk\_getSaveFile** dialog box commands. This option will preselect the filter from the **-filetypes** list based on the type name. # Rationale The standard Open and Save dialog boxes currently allow you to seed the initial directory and the initial file. The path returned by the call can be saved and used to seed future calls to these dialgo boxes. However, the selected filter cannot be choosen nor read, nor is examining the returned file path sufficient to guess at the filter setting. One common aspect of good U/I design is remembering prior selections so the user does not have to repeat actions each time a dialog is used. The initial directory and initial file options provide partially for this ability in the File dialog boxes, but the selected filter type is not controllable. The filter selection can also be used for format selection when the file extension is insufficient or not present as is typical in the Mac OS X environment. One example might be a file with the extension .xml, where the file contents may be data, schema, or a dtd. By selecting "XML Schema", over "XML DTD", the user can control the formatting of the .xml file. By giving the application access to the filter selection, the UI can be made friendlier to the user. # Proposed Change Since the requirement is to be able to set and read the filter selection, the proposal is to use a variable to control and access this feature of the dialog boxes. This is done by adding a **-typevariable** option to **tk\_getOpenFile** and **tk\_getSaveFile**. The variable specified is read once at the begining to select the appropriate filter. If the variable does not exist, or it's value does not match any filter typename, or is empty \(\{\}\), the dialog box will revert to the default behavior of selecting the first filter in the list. When the dialog box is closed by using the Ok button, the variable is set to the typename value of the currently selected filter. The variable will not be updated while the dialog box is open and the user makes various selections. If the dialog box is closed using the Cancel button, the variable is not changed. Example: set types { {{Text Files} {.txt} } {{TCL Scripts} {.tcl} } {{C Source Files} {.c} TEXT} {{GIF Files} {.gif} } {{GIF Files} {} GIFF} {{All Files} * } } set type {C Source Files} tk_getOpenFile -filetypes $types -typevariable type set type => {TCL Scripts} To preselect .c files for the filter, set type \{C Source Files\}. If the filter is changed to \{TCL Scripts\}, for example, the variable "type" is modified to the value \{TCL Scripts\}. # Reference Implementation A reference implementation will be posted to Tk patches<http://sf.net/tracker/?func=detail&aid=1156388&group_id=12997&atid=312997> . I have modified _tkfbox.tcl_ and _tkWinDialog.c_. I have not looked at MacOSX yet. # Acknowledgement Thanks to Michael Kirkham and Donal Fellows for their valuable suggestions. # Copyright This document has been placed in the public domain. |
Name change from tip/243.tip to tip/243.md.
|
| < | < | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 243: Supply Find Dialog for the Text Widget Author: Rüdiger Härtel <[email protected]> State: Draft Type: Project Vote: Pending Created: 16-Mar-2005 Tcl-Version: 8.7 Post-History: Keywords: Tk ----- # Abstract This TIP adds a _find dialog_ to the Tk **text** widget. # Rationale In using the **text** widget it often is a desire to search the input, and the text widget itself provides already all means to search text. However, until now there is no GUI based support, so each application developer needing it has to reinvent much of this particular wheel. Tk should provide a scripted find dialog in its library scripts so that simple applications can be built more easily and to a higher quality. Additionally, a _replace dialog_ is desirable, and it should be developed at the same time. # Reference Implementation A reference implementation for a _find dialog_ is available at <http://sf.net/tracker/?func=detail&aid=1167420&group_id=12997&atid=312997> . # Example Use package require Tk namespace import ::msgcat::* mclocale en ::msgcat::mcset en LblSearchString "Search String" ::msgcat::mcset en LblDirection "Direction" ::msgcat::mcset en ChkBtnFindCaseOpt "Case" ::msgcat::mcset en ChkBtnFindRegexpOpt "Regexp" ::msgcat::mcset en RdoBtnFindDirOpt1 "Forward" ::msgcat::mcset en RdoBtnFindDirOpt2 "Backward" ::msgcat::mcset en BtnFind " Find " ::msgcat::mcset en BtnFindNext " Next " ::msgcat::mcset en BtnClose " Close " set b1 .button set t1 .t1 button $b1 -text Find -command [list \ tk_textFind $t1 -searchstring hallo -highlightcolor green \ -title "Find Dialog"] text $t1 grid $b1 -row 0 -column 1 grid $t1 -row 1 -column 0 -columnspan 2 set fd [open [file join . tk_find.tcl] r] set content [read $fd] close $fd $t1 insert 0.0 $content set content "" # Copyright This document is in the public domain. |
Name change from tip/244.tip to tip/244.md.
|
| < | < | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 244: PNG Photo Image Support for Tk Author: Michael Kirkham <[email protected]> State: Final Type: Project Vote: Done Created: 22-Mar-2005 Post-History: Discussions-To: news:comp.lang.tcl Tcl-Version: 8.6 ----- # Abstract Tk's photo image type has had support for alpha channels internally since version 8.3. However, to date there is no photo format in the core that exposes this functionality. This TIP proposes adding support for the PNG \(Portable Network Graphics\) format. # Rationale There is a current push for "beautifying" Tcl/Tk with more modern appearing widgets and default configuration options. One method that can provide significant improvement in appearance is the use of images with alpha channels for antialiasing and smooth blending into the background of the GUI. While the Tk core supports alpha channels, this support is neither exposed through the Tk\_GetColor\(\) format used by **image put** and similar interfaces, nor by the only photo image format, GIF, which allows only fully-opaque or fully-transparent pixels. Instead, a third party package is currently required to add a format supporting alpha channels, which may not have a suitable license or increase the number of external dependencies unreasonably. The PNG image format is an open standard supporting a wide range of colors, from 1 bit per pixel black and white to 16 bit per pixel RGBA, with loss-less compression. It's becoming increasingly widely used as the image format of choice in many areas including GUI and web page design for its color range, alpha support and small image size. As such it is the obvious choice for adding alpha support to Tk. An implementation can be light-weight and not add any new dependencies \(such as on libpng\) to Tk: while the format also depends on the zlib format for compression, [[234]](234.md) proposes zlib support for the Tcl core. # Specification The implementation shall use the _Tk\_CreatePhotoImageFormat\(\)_ mechanisms to supply handlers to Tk for PNG support. The implementation must: 1. Support the full range of color types and bit depths allowed and required by the PNG standard, including alpha channels and boolean transparency. 2. Support reading of interlaced images. 3. Support base64 encoded data through **image create photo -data**. 4. Otherwise conform to the requirements of the PNG specification, such as the handling of unsupported ancillary and critical chunks and support for all required filter types. In addition, the implementation should: 5. Support exporting to the PNG format through **image data** and **image write**. 6. Allow modification of the overall alpha transparency of imported images through **-format "png -alpha value"**. 7. Allow application of display gamma \(if known\) in conjunction with the "gAMA" chunk of imported images, if present, through **-format "png -gamma value"**. # Reference Implementation A reference implementation is available <http://www.muonics.com/FreeStuff/TkPNG/> . This reference implementation has been done as a loadable extension, but requires only the file _tkImgPNG.c_ and the _Tk\_CreatePhototoImageFormat\(\)_ invocation from _tkImgPNGInit.c_ to be added to _CreateTopLevelWindow\(\)_ in _tkWindow.c_ to be built into the core. The only new dependency for this implementation is on zlib. It currently meets requirements 1 - 6; it does not implement 7. ## Notes 1. It is understood that there will likely be some reformatting required to conform to the Tcl Style Guide if this TIP is accepted. 2. Performance is currently comparable to Img for small \(i.e., toolbar button\) sized images - a little faster or slower depending on the image. It seems to be somewhat slower for larger images, but there may be room for additional optimizations. 3. At this time there is a bug \(1155596\) in Tk Aqua bevel buttons that will crash Tk if images with partially transparent pixels are used. This is not the fault of the extension, but occurs also with Img. The author is attempting to find a fix, however. 4. The implementation has been tested with PngSuite, which is fairly exhaustive, but more tests would probably be useful. # Copyright This document has been placed in the public domain. # References * PngSuite <http://www.schaik.com/pngsuite/pngsuite.html> * Portable Network Graphics \(PNG\) Specification and Extensions <http://www.libpng.org/pub/png/spec/> * zlib Compression Library <http://www.gzip.org/zlib/> * zlib Specifications <http://www.gzip.org/zlib/zlib_docs.html> |
Name change from tip/245.tip to tip/245.md.
|
| < | < | | | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 245: Discover User Inactivity Time Author: Pascal Scheffers <[email protected]> Author: Reinhard Max <[email protected]> Author: Neil Madden <[email protected]> State: Final Type: Project Vote: Done Created: 15-Apr-2005 Post-History: Keywords: Tk Tcl-Version: 8.5 ----- # Abstract This TIP proposes a new subcommand, **inactive**, to the **tk** command, as well as **Tk\_GetUserInactiveTime** and **Tk\_ResetUserInactiveTime** C functions to discover the number of milliseconds the user has been inactive and reset that timer to zero respectively. For most environments, this is the time since the user last used the keyboard or mouse. # Rationale User inactivity is used by screen-savers, chat applications and for security conscious applications to quit or lock themselves after some inactive time has elapsed. It would make it easier for authors of these kinds of applications to use Tk if there was a simple way to get the length of time which the user has been inactive, which is information available on all supported platforms. Applications that take some kind of user input from channels that bypass the system's mechanisms for detecting user activity might want to tell the system to reset the inactivity timer because they received input that has to be treated as user activity. An example for this would be barcode readers connected via serial lines that are read directly by the application. # Specification ## Tcl API A single new subcommand will be added to **tk**, **inactive**. This command takes an optional argument ?**-displayof** _window_?. It returns a positive integer, the number of milliseconds since the last time the user interacted with the system. If the -displayof option is given then the return value refers to the display of _window_; otherwise it refers to the display of the application's main window. If querying the user inactive time is not supported by the system, **tk inactive** will return -1. If the literal string **reset** is given as an additional argument, the timer is reset and an empty string is returned. > **tk** **inactive** ?**-displayof** _window_? ?**reset**? ## C API long **Tk\_GetUserInactiveTime**\(_display_\) Display \*display \(in\): used to determine which display to query for user inactive time. **Tk\_GetUserInactiveTime\(\)** returns a positive integer, the number of milliseconds since the last time the user interacted with the system \(note that this is not necessarily the time since the user interacted with the application.\) void **Tk\_ResetUserInactiveTime**\(_display_\) Display \*display \(in\): used to determine on which display the user inactivity timer is to be reset. # Safe Interpreters User inactive time can be used for timing attacks and will not be made available in safe interpreters, **tk inactive** will return -1 in safe interpreters. Calling **tk inactive reset** in a safe interpreter will throw an error. # Implementation Notes Windows 2000 and later have _GetLastInputInfo_ to obtain the information, earlier platforms do not have this symbol in user32.dll. This symbol will be dynamically obtained upon the first call of _Tk\_UserInactiveTime\(\)_ on windows. If the symbol is not available, _Tk\_UserInactiveTime\(\)_ will return -1. _GetLastInputInfo\(\)_ has no notion of displays, and as a result the display argument is ignored. The behaviour of the command is unknown for terminal services, remote desktop, VNC, Citrix and other remote screen systems. For X, this patch introduces two additional library dependencies - libXext and libXss. The authors do not know if a similar situation to Windows could exist on the X Window System, where the build host has libXss, and yet not all installations for that platform have libXss. A proper solution for that scenario would require an additional TIP to export TclLoadFile, Tcl\_FSLoadFile is not sufficient, to resolve the symbols at runtime. \(The other library, libXext, is virtually universally available.\) For Win9x, Microsoft has published example code at <http://www.microsoft.com/msj/0200/c/c0200.aspx> . # Reference Implementation A reference implementation is available as Patch \#1185731 on SourceForge<http://sf.net/support/tracker.php?aid=1185731> . # Comments [ Insert here please ] # Copyright This document has been placed in the public domain. |
Name change from tip/246.tip to tip/246.md.
|
| < | < | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 246: Unify Pattern Matching Author: Reinhard Max <[email protected]> State: Draft Type: Project Vote: Pending Created: 27-Apr-2005 Post-History: Keywords: pattern,match,glob,exact,regexp,case sensitive,Tcl Tcl-Version: 8.7 ----- # Abstract Many Tcl commands take arguments that are patterns to match against. Some of these commands allow options to specify whether the pattern should be treated as a literal, a glob pattern, or a regular expression, and whether or not matching should be case sensitive. This TIP proposes a unique set of options for all commands that accept pattern arguments. # Rationale It is hard to memorize which of the commands that take a pattern argument allows to modify the matching mode, and in which way. With this TIP in place pattern matching will be orthogonal throughout Tcl, so the rules learned once can be applied to every command that uses pattern matching. # Current situation The following commands currently take pattern arguments with varying combinations of switches to specify their behaviour: * **array get** _arrayName_ ?_pattern_? * **array names** _arrayName_ ?_mode_? ?_pattern_? * **array values** _arrayName_ ?_pattern_? * **array unset** _arrayName_ ?_pattern_? * **dict filter** _dictionaryValue_ **key** _globPattern_ * **dict filter** _dictionaryValue_ **value** _globPattern_ * **dict keys** _dictionaryValue_ ?_globPattern_? * **dict values** _dictionaryValue_ ?_globPattern_? * **lsearch** ?_options..._? _list pattern_ * **parray** _arrayName_ ?_pattern_? * **string match** ?**-nocase**? _pattern string_ * **switch** ?_options..._? _string pattern body_ * **namespace children** ?_namespace_? ?_pattern_? * **namespace export** ?**-clear**? ?_pattern pattern ..._? * **namespace forget** ?_pattern pattern ..._? * **namespace import** ?**-force**? ?_pattern pattern ..._? * **info commands** ?_pattern_? * **info functions** ?_pattern_? * **info globals** ?_pattern_? * **info locals** ?_pattern_? * **info procs** ?_pattern_? * **info vars** ?_pattern_? * **registry keys** _keyName_ ?_pattern_? * **registry values** _keyName_ ?_pattern_? The following commands which also take pattern arguments are outside the scope of this TIP: * Commands that match patterns against file names: **auto\_import**, **auto\_mkindex**, **pkg\_mkIndex**, **tcltest**. * Commands that use regular expressions by design: **regexp**, and **regsub**. * The **case** command, because it is deprecated # Specification The commands listed above shall allow for two optional switches, one that specifies the matching mode, and can be **-exact**, **-glob**, or **-regexp**, and one that specifies case sensitivity, and can be **-case**, or **-nocase**. Their current behaviour shall become the default behaviour in absence of the respective switch. \(Some commands may accept other switches as well.\) Also shall there be two new manual pages, one that describes glob matching similar to the _re\_syntax_ page, and one that describes the pattern matching options. These manuals shall be referenced by the manuals for the individual commands instead of repeating the detailed descriptions. # Objections Some of the mentioned commands could become somewhat slower when they need to check for more options. This needs to be checked when implementing this TIP. # Reference Implementation There is no reference implementation yet. The idea is to have common code for option checking, and matching, that can be used by all mentioned commands. That way it would be easy to add new algorithms or options, and have them immediately available for all commands that can do pattern matching. The C API for this will first be worked out as a private API when creating the reference implementation and later be published by a separate TIP, so that extensions can also make use of it. # Notes There might be need for a similar unification in Tk as well, but that's outside the scope of this TIP, and should be easy to add once this TIP is implemented so that Tcl provides the needed infrastructure. # Copyright This document has been placed in the public domain. |
Name change from tip/247.tip to tip/247.md.
|
| < | | | | | < | | | > | | | | | | | | | | 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 | # TIP 247: Tcl/Tk Engineering Manual State: Draft Type: Informational Vote: Pending Post-History: Author: John K. Ousterhout <[email protected]> Author: Donal K. Fellows <[email protected]> Created: 01-Jun-2005 ----- # Abstract This document describes the set of conventions used for writing C code to go into the Tcl and Tk core. It is also recommended that extensions be written in the same style for clarity. ## NOTE _A transcription of the original version \(dated September 1, 1994\) of this file into PDF is available online at <http://tcl.sourceforge.net/engManual.pdf> - Donal K. Fellows_ _Also note that the figures might lag the text. We'll fix them eventually._ # Introduction This is a manual for people who are developing C code for Tcl, Tk, and their extensions and applications. It describes a set of conventions for writing code and the associated test scripts. There are two reasons for the conventions. First, the conventions ensure that certain important things get done; for example, every procedure must have documentation that describes each of its arguments and its result, and there must exist test scripts that exercise every line of code. Second, the conventions guarantee that all of the Tcl and Tk code has a uniform style. This makes it easier for us to use, read, and maintain each other's code. Most of the conventions originated in the Sprite operating system project at U.C. Berkeley. At the beginning of the Sprite project my students and I decided that we wanted a uniform style for our code and documentation, so we held a series of meetings to choose the rules. The result of these meetings was a document called _The Sprite Engineering Manual_. None of us was completely happy with all the rules, but we all managed to live by them during the project and I think everyone was happy with the results. When I started work on Tcl and Tk, I decided to stick with the Sprite conventions. This document is based heavily on _The Sprite Engineering Manual_. There are few things that I consider non-negotiable, but the contents of this manual are one of them. I don't claim that these conventions are the best possible ones, but the exact conventions don't really make that much difference. The most important thing is that we all do things the same way. Given that the core Tcl and Tk code follows the conventions, changing the rules now would cause more harm than good. |
︙ | ︙ | |||
70 71 72 73 74 75 76 | Section 4 desribes the Tcl/Tk naming conventions. Section 5 presents low-level coding conventions, such as how to indent and where to put curly braces. Section 6 contains a collection of rules and suggestions for writing comments. Section 7 describes how to write and maintain test suites. Section 8 describes how to make code portable without making it unreadable too. Section 9 contains a few miscellaneous topics, such as keeping a change log. | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 | Section 4 desribes the Tcl/Tk naming conventions. Section 5 presents low-level coding conventions, such as how to indent and where to put curly braces. Section 6 contains a collection of rules and suggestions for writing comments. Section 7 describes how to write and maintain test suites. Section 8 describes how to make code portable without making it unreadable too. Section 9 contains a few miscellaneous topics, such as keeping a change log. # Packages and Header Files Tcl applications consist of collections of _packages_. Each package provides code to implement a related set of features. For example, Tcl itself is a package, as is Tk; various extensions such as Tcl-DP, TclX, Expect, and BLT are also packages. Packages are the units in which code is developed and distributed: a single package is typically developed by a single person or group and distributed as a unit. One of the best things about Tcl is that it is possible to combine many independently-developed packages into a single application; packages should be designed with this in mind. This section describes the file structure of packages with an emphasis on header files; later sections discuss conventions for code files. You may also wish to review Chapter 31 of the Tcl book for additional information on packages, such as how to interface them to the rest of an application. ## Package Prefixes Each package has a unique short _prefix_. The prefix is used in file names, procedure names, and variable names in order to prevent name conflicts with other packages. For example, the prefix for Tcl is tcl; Tcl's exported header file is called tcl.h and exported procedures and variables have names like Tcl\_Eval. ## Version Numbers Each package has a two-part version number such as 7.4. The first number \(7\) is called the major version number and the second \(4\) is called the minor version number. The version number changes with each public release of the package. If a new release contains only bug fixes, new features, and other upwardly compatible changes, so that code and scripts that worked with the old version will also work with the new version, then the minor version number increments and the major version number stays the same \(e.g., from 7.4 to 7.5\). If the new release contains substantial incompatibilities, so that existing code and scripts will have to be modified to run with the new version, then the major version number increments and the minor version number resets to zero \(e.g., from 7.4 to 8.0\). ## Overall Structure A package typically consists of several code files, plus at least two header files, plus additional files for building and configuring the package, such as a Makefile and a configure.in file for the autoconf program. The header files for a package generally fall into the following categories: * A _package header file_, which is named after the package, such as tcl.h or tk.h. This header file describes all of the externally-visible features of the package, such as procedures, global variables, and structure declarations. The package header file is eventually installed in a system directory such as /usr/local/include; it is what clients of the package \#include in their C code. As a general rule of thumb, the package header file should define as few things as possible: it's very hard to change an exported feature since it breaks client code that uses the package, so the less you export, the easier it will be to make changes to the package. Thus, for example, try not to make the internal fields of structures visible in package header files. * An _internal header file_, which is typically \#included by all of the C files in the package. The internal header file has a name like tclInt.h or tkInt.h, consisting of the the package prefix followed by Int.h. The internal header file describes features that are used in multiple files within the package but aren't exported out of the package. For example, key package structures and internal utility procedures are defined in the internal header file. The internal header file should also contain \#includes for other headers that are used widely within the package, so they don't have to be included over and over in each code file. As with the package header, the internal header file should be as small as possible: structures and procedures that are only used in a single C file in the package should not appear in it. * A _porting header file_, which contains definitions that hide the differences between the systems on which the package can be used. The name of the porting header should consist of the package prefix follwed by Port.h, such as tclPort.h. * Other internal header files for various subpackages within the package. For example, there is a file tkText.h in Tk that is shared among all the files that implement text widgets and another file tkCanvas.h that is shared among all the widgets implementing canvases. I recommend having as few header files as possible in each package. In almost all cases a package header file, a single internal header file, and a porting header file will be sufficient, and in many cases the porting header file may not be necessary. The internal header file should automatically \#include the package header file and perhaps even the porting header file, so each C file in the package only needs to \#include one or at most two header files. I recommend keeping the porting header separate from the internal header file in order to maintain a clean separation between porting code and the rest of the module. Other internal headers should only be necessary in unusual cases, such as the Tk text and canvas widgets \(each of tkText.h and tkCanvas.h is many hundred lines long, due to the complexity of the widgets, and they are needed only in the source files that implement the particular widgets, so I thought it would be easier to manage these headers separately from tkInt.h\). If you have lots of internal header files, such as one for each source file, then you will end up with lots of \#include statements in each C file and you'll find that either _\(a\)_ you \#include every header in every C file \(in which case there's not much advantage to having the separate .h files\) or _\(b\)_ you are constantly adding and deleting \#include statements as you modify source files. ## Header File Structure Figure 1 illustrates the format of a header file. Your header files should follow this structure exactly: same indentation, same order of information, and so on. To make this as easy as possible, the directory engManual in the Tcl source tree contains templates for various pieces of source files. For example, the file proto.h contains a template for a header file; there are also templates for code files and procedure headers. You should be able to set up your editor to incorporate the templates when needed, then you can modify them for the particular situation in which they are used. This should make it easy for you to conform to the conventions without a lot of typing overhead. ![Figure 1. An example of a header file. The file](../assets/247fig1.png) engManual/proto.h contains a template for header files. Each header file contains the following parts, which are labelled in Figure 1: Abstract: the first few lines give the name of the file plus a short description of its overall purpose. Copyright notice: this protects the ownership of the file and controls distribution; different notices may be used on different files, depending on whether the file is to be released freely or restricted. The wording in copyright notices is sensitive \(e.g. the use of upper case is important\) so don't make changes in notices without checking with a legal authority. Revision string: the contents of this string are managed automatically by the source code control system for the file, such as RCS or SCCS \(RCS is used in the example in the figure\). It identifies the file's current revision, date of last modification, and so on. Multiple include \#ifdef: when a large application is developed with many related packages, it is hard to arrange the \#include statements so that each include file is included exactly once For example, files a.h and b.h might both include c.h, and a particular code file might include both a.h and b.h. This will cause c.h to be processed twice, and could potentially result in compiler errors such as multiply-defined symbols. With the recursion \#ifdef, plus the matching \#endif at the end of the file, the header file can be \#included multiple times without problems. The symbol \_TCL is defined the first time the header file is included; if the header is included again the presence of the symbol causes the body of the header file to be skipped. The symbol used in any given header file should be the same as the name of the header file except with the .h stripped off, a \_ prepended, and everything else capitalized. Version defines: for each package, three symbols related to the current version number should be defined. The first gives the full version number as a string, and the second and third give the major and minor numbers separately as integers. The names for these symbols should be derived from the package prefix as in Figure 1. Declarations: the rest of the header file consists of declarations for the things that are exported from the package to its clients. Most of the conventions for coding these declarations will be discussed later. When declaring variables and procedures, use EXTERN instead of extern to declare them external. The symbol EXTERN can then be \#defined to either extern or extern "C" to allow the header file to be used in both C and C\+\+ programs. The header file tcl.h contains code to \#define the EXTERN symbol; if your header file doesn't \#include tcl.h, you can copy the code from tcl.h to your header file. ## \_ANSI\_ARGS\_ Prototypes Procedure prototypes _may_ use the \_ANSI\_ARGS\_ macro as shown in Figure 1. \_ANSI\_ARGS\_ makes it possible to write full procedure prototypes for the normal case where an ANSI C compiler will be used, yet it also allows the file to be used with older non-ANSI compilers. To use \_ANSI\_ARGS\_, specify the entire argument list, including parentheses, as an argument to the \_ANSI\_ARGS\_ macro; \_ANSI\_ARGS\_ will evaluate to either this argument list or \(\), depending on whether or not an ANSI C compiler is being used. The \_ANSI\_ARGS\_ macro is defined in _tcl.h_. In the argument lists in procedure prototypes, be sure to specify names for the arguments as well as their types. The names aren't required for compilation \(for example, the declaration for Tcl\_Eval could have been written as EXTERN int Tcl_Eval _ANSI_ARGS_((Tcl_Interp *, const char *)); in Figure 1\) but the names provide additional information about the arguments. Note that for modern code, it is usually preferred to omit this macro, resulting in the above example looking like: EXTERN int Tcl_Eval(Tcl_Interp *interp, const char *scriptPtr); ## MODULE\_LOCAL Prototypes _\(Not yet shown in any figure, to be used from Tcl 8.5 onwards for the Tcl and Tk core only.\)_ Where a function is only exported so that it may be accessed from a file other than the file that declares it, that function should be declared as being MODULE\_LOCAL. While this does not have an effect with all toolchains, some \(such as the ones used for MS Windows and MacOS X\) can use this information during the linking stage to ensure that the symbol in the resulting library cannot be linked against by external code. This is useful for keeping the internal implementation of library code away from casual misuse. Example of usage: MODULE_SCOPE int TclIsLocalScalar(const char *src, int len); # How to Organize a Code File Each source code file should contain a related set of procedures, such as the implementation of a widget or canvas item type, or a set of procedures to implement hash tables. Before writing any code you should think carefully about what functions are to be provided and divide them up into files in a logical way. In my experience, the most manageable size for files is usually in the range of 500-2000 lines. If a file gets much larger than this, it will be hard to remember everything that the file does. If a file is much shorter than this, then you may end up with too many files in a directory, which is also hard to manage. Code files are divided into pages separated by formfeed \(control-L\) characters. The first page of the file is a header page containing information that is used throughout the file. Each additional page of the file contains one procedure. This approach has two advantages. First, when you print a code file each procedure header will start at the top of the page, which makes for easier reading. Second, you can browse through all of the procedures in a file by searching for the formfeed characters. ## The File Header Page The first page of a code file is a header page. It contains overall information that is relevant throughout the file, which consists of everything but the definitions of the file's procedures. The header page typically has six parts, as shown in Figure 2: ![Figure 2. An example of a header page. Part of the text of the](../assets/247fig2.png) copyright notice has been omitted. The file engManual/proto.c contains a template for a header page. Abstract: the first few lines give the name of the file and a brief description of the overall functions provided by the file, just as in header files. Copyright notice: protects ownership of the file, just as in header files. Revision string: similar to the revision strings in header files, except that its value is used to initialize a string variable. This allows the revision information to be checked in the executable object file. Include statements: all of the \#include statements for the file should appear on the header file just after the version string. In general there should be very few \#include statements in a given code file, typically just for the package's internal header file and porting header file. If additional \#includes are needed they should appear in the package's internal header file or porting header file. Declarations: any structures used only in this file should be declared on the header page \(exported structures must be declared in header files\). In addition, if the file defines any static or global variables then they should be declared on the header page. This makes it easy to tell whether or not a file has static variables, which is important if the file is ever used in a multi-threaded environment. Static variables are generally undesirable and should be avoided as much as possible. Prototypes: procedure prototypes for procedures referenced only in this file should appear at the very end of the header page \(prototypes for exported procedures must appear in the package header file\). Use the \_ANSI\_ARGS\_ macro described in Section 2.5. Please structure your header pages in exactly the order given above and follow the syntax of Figure 2 as closely as possible. The file engManual/proto.c provides a template for a header page. Source files should never contain extern statements. Instead, create header files to hold the extern statements and \#include the header files. This makes code files easier to read and makes it easier to manage the extern statements, since they're centralized in .h files instead of spread around dozens of code files. For example, the internal header file for a package has extern statements for all of the procedures that are used by multiple files within the package but aren't exported outside it. ## Procedure Headers Each page after the first one in a file should contain exactly one procedure. The page should begin with a procedure header that gives overall documentation for the procedure, followed by the declaration and body for the procedure. See Figures 3 and 4 for examples. The header should contain everything that a caller of the procedure needs to know in order to use the procedure, and nothing else. It consists of three parts: ![Figure 3. The header comments and declaration for a procedure.](../assets/247fig3.png) The file engManual/prochead contains a template for this information. ![Figure 4. The header for a procedure with side effects.](../assets/247fig4.png) Abstract: the first lines in the header give the procedure's name, followed by a brief description of what the procedure does. This should not be a detailed description of how the procedure is implemented, but rather a high-level summary of its overall function. In some cases, such as callback procedures, I recommend also describing the conditions under which the procedure is invoked and who calls the procedure, as in Figure 4. |
︙ | ︙ | |||
378 379 380 381 382 383 384 | section should not describe every internal variable modified by the procedure. It should simply provide the sort of information that users of the procedure need in order to use the procedure correctly. See Figure 4 for an example. The file engManual/prochead contains a template for a procedure header, which you can include from your editor to save typing. Follow the syntax of Figures | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | < > | | | | | | | | | < | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | < > | | | | < > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 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 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 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 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 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 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 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 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 1320 1321 1322 1323 1324 1325 1326 1327 | section should not describe every internal variable modified by the procedure. It should simply provide the sort of information that users of the procedure need in order to use the procedure correctly. See Figure 4 for an example. The file engManual/prochead contains a template for a procedure header, which you can include from your editor to save typing. Follow the syntax of Figures 3 and 4 exactly \(same indentation, double-dash after the procedure name, etc.\). The Results and Side Effects parts of the header may be omitted _only_ if the function has no results or side effects respectively. ## Procedure Declarations The procedure declaration should also follow exactly the syntax in Figures 3 and 4. The first line gives the type of the procedure's result. All procedures must be typed: use void if the procedure returns no result. The second line gives the procedure's name and its argument list. If there are many arguments, they may spill onto additional lines \(see Sections 5.1 and 5.5 for information about indentation\). After this come the declarations of argument types, one argument per line, indented, with a comment after each argument giving a brief description of the argument. Every argument must be explicitly declared, and every argument must have a comment. This form for argument declarations is the old form that predates ANSI C. It's important to use the old form so that your code will compile on older pre-ANSI compilers. Hopefully there aren't too many of these compilers left, and perhaps in a few years we can switch to the ANSI form, but for now let's be safe. Every procedure should also have an ANSI-style prototype either on the file's header page or in a header file, so this approach still allows full argument checking. _Note that_ for new code it is preferred to use ANSI declarations, especially if the code will not build on non-ANSI compilers. ## Parameter Order Procedure parameters may be divided into three categories. In parameters only pass information into the procedure \(either directly or by pointing to information that the procedure reads\). Out parameters point to things in the caller's memory that the procedure modifies. In-out parameters do both. Below is a set of rules for deciding on the order of parameters to a procedure: 1. Parameters should normally appear in the order in, in/out, out, except where overridden by the rules below. 2. If there is a group of procedures, all of which operate on structures of a particular type, such as a hash table, the token for the structure should be the first argument to each of the procedures. 3. When two parameters are the address of a callback procedure and a ClientData value to pass to that procedure, the procedure address should appear in the argument list immediately before the ClientData. 4. If a callback procedure takes a ClientData argument \(and all callbacks should\), the ClientData argument should be the first argument to the procedure. Typically the ClientData is a pointer to the structure managed by the callback, so this is really the same as rule 2. ## Procedure Bodies The body of a procedure follows the declaration. See Section 5 for the coding conventions that govern procedure bodies. The curly braces enclosing the body should be on separate lines as shown in Figures 3 and 4. # Naming Conventions Choosing names is one of the most important aspects of programming. Good names clarify the function of a program and reduce the need for other documentation. Poor names result in ambiguity, confusion, and error. For example, in the Sprite operating system we spent four months tracking down a subtle problem with the file system that caused seemingly random blocks on disk to be overwritten from time to time. It turned out that the same variable name was used in some places to refer to physical blocks on disk, and in other places to logical blocks in a file; unfortunately, in one place the variable was accidentally used for the wrong purpose. The bug probably would not have occurred if different variable names had been used for the two kinds of block identifiers. This section gives some general principles to follow when choosing names, then lists specific rules for name syntax, such as capitalization, and finally describes how to use package prefixes to clarify the module structure of your code. ## General Considerations The ideal variable name is one that instantly conveys as much information as possible about the purpose of the variable it refers to. When choosing names, play devil's advocate with yourself to see if there are ways that a name might be misinterpreted or confused. Here are some things to consider: 1. Are you consistent? Use the same name to refer to the same thing everywhere. For example, in the Tcl implementation the name _interp_ is used consistently for pointers to the uservisible Tcl\_Interp structure. Within the code for each widget, a standard name is always used for a pointer to the widget record, such as _butPtr_ in the button widget code and _menuPtr_ in the menu widget code. 2. If someone sees the name out of context, will they realize what it stands for, or could they confuse it with something else? For example, in Sprite the procedure for doing byte-swapping and other format conversion was originally called Swap\_Buffer. When I first saw that name I assumed it had something to do with I/O buffer management, not reformatting. We subsequently changed the name to Fmt\_Convert. 3. Could this name be confused with some other name? For example, it's probably a mistake to have two variables _s_ and _string_ in the same procedure, both referring to strings: it will be hard for anyone to remember which is which. Instead, change the names to reflect their functions. For example, if the strings are used as source and destination for a copy operation, name them _src_ and _dst_. 4. Is the name so generic that it doesn't convey any information? The variable _s_ from the previous paragraph is an example of this; changing its name to _src_ makes the name less generic and hence conveys more information. ## Basic Syntax Rules Below are some specific rules governing the syntax of names. Please follow the rules exactly, since they make it possible to determine certain properties of a variable just from its name. 1. Variable names always start with a lower-case letter. Procedure and type names always start with an upper-case letter. int counter; extern char *FindElement(); typedef int Boolean; 2. In multi-word names, the first letter of each trailing word is capitalized. Do not use underscores as separators between the words of a name, except as described in rule 5 below and in Section 4.3. int numWindows; 3. Any name that refers to a pointer ends in Ptr. If the name refers to a pointer to a pointer, then it ends in PtrPtr, and so on. There are two exceptions to this rule. The first is for variables that are opaque handles for structures, such as variables of type Tk\_Window. These variables are actually pointers, but they are never dereferenced outside Tk \(clients can never look at the structure they point to except by invoking Tk macros and procedures\). In this case the Ptr is omitted in variable names. The second exception to the rule is for strings. We decided in Sprite not to require Ptr suffixes for strings, since they are always referenced with pointers. However, if a variable holds a pointer to a string pointer, then it must have the Ptr suffix \(there's just one less level of Ptr for strings than for other structures\). TkWindow *winPtr; char *name; char **namePtr; 4. Variables that hold the addresses of functions should have names ending in Proc \(for "procedure"\). Typedefs for these variables should also have names ending in Proc. typedef void (Tk_ImageDeleteProc)(ClientData clientData); 5. \#defined constants and macros have names that are all capital letters, except for macros that are used as replacements for procedures, in which case you should follow the naming conventions for procedures. If names in all caps contain multiple words, use underscores to separate the words. #define NULL 0 #define BUFFER_SIZE 1024 #define Min(a,b) (((a) < (b)) ? (a) : (b)) 6. Names of programs, Tcl commands, and keyword arguments to Tcl commands \(such as Tk configuration options\) are usually entirely in lower case, in spite of the rules above. The reason for this rule is that these names are likely to typed interactively, and I thought that using all lower case would make it easier to type them. In retrospect I'm not sure this was a good idea; in any case, Tcl procedure and variable names should follow the same rules as C procedures and variables. ## Names Reflect Package Structure Names that are exported outside a single file must include the package prefix in order to make sure that they don't conflict with global names defined in other packages. The following rules define how to use package prefixes in names: 1. If a variable or procedure or type is exported by its package, the first letters of its name must consist of the package prefix followed by an underscore. Only the first letter of the prefix is ever capitalized, and it is subject to the capitalization rules from Section 4.2. The first letter after the prefix is always capitalized. The first example below shows an exported variable, and the second shows an exported type and exported procedure. extern int tk_numMainWindows; extern Tcl_Interp *Tcl_CreateInterp(void); 2. If a module contains several files, and if a name is used in several of those files but isn't used outside the package, then the name must have the package prefix but no underscore. The prefix guarantees that the name won't conflict with a similar name from a different package; the missing underscore indicates that the name is private to the package. extern void TkEventDeadWindow(TkWindow *winPtr); 3. If a name is only used within a single procedure or file, then it need not have the module prefix. To avoid conflicts with similar names in other files, variables and procedures declared outside procedures must always be declared static if they have no module prefix. static int initialized; ## Standard Names The following variable names are used consistently throughout Tcl and Tk. Please use these names for the given purposes in any code you write, and don't use the names for other purposes. clientData: Used for variables of type ClientData, which are associated with callback procedures. interp: Used for variables of type Tcl\_Interp. These are the \(mostly\) opaque handles for interpreters that are given to Tcl clients. These variables should really have a Ptr extension, but the name was chosen at a time when interpreters were totally opaque to clients. iPtr: Used for variables of type Interp \*, which are pointers to Tcl's internal structures for interpreters. Tcl procedures often have an argument named interp, which is copied into a local variable named iPtr in order to access the contents of the interpreter. nextPtr: A field with this name is used in structures to point to the next structure in a linked list. This is usally the last field of the structure. tkwin: Used for variables of type Tk\_Window, which are opaque handles for the window structures managed by Tk. winPtr: Used for variables of type TkWindow \*, which are pointers to Tk's internal structures for windows. Tk procedures often take an argument named tkwin and immediately copy the argument into a local variable named winPtr in order to access the contents of the window structure. # Low-Level Coding Conventions This section describes several low-level syntactic rules for writing C code. The reason for having these rules is not because they're better than all other ways of structuring code, but in order to make all our code look the same. ## Indents are 4 Spaces Each level of indentation should be four spaces. There are ways to set 4-space indents in all editors that I know of. Be sure that your editor really uses four spaces for the indent, rather than just displaying tabs as four spaces wide; if you use the latter approach then the indents will appear eight spaces wide in other editors. If you use tabs, they _must_ be to 8-space indents. ## Code Comments Occupy Full Lines Comments that document code \(as opposed to declarations\) should occupy full lines, rather than being tacked onto the ends of lines containing code. The reason for this is that side-byside comments are hard to see, particularly if neighboring statements are long enough to overlap the side-by-side comments. Comments must have exactly the structure shown in Figure 5, including a leading /\* line, a trailing \*/ line, and additional blank lines above and below. The leading blank line can be omitted if the comment is at the beginning of a block, as is the case in the second comment in Figure 5. Each comment should be indented to the same level as the surrounding code. Use proper English in comments: write complete sentences, capitalize the first word of each sentence, and so on. ![Figure 5. Comments in code have the form shown above, using](../assets/247fig5.png) full lines, with lined-up stars, the /\* and \*/ symbols on separate lines, and blank separator lines around each comment \(except that the leading blank line can be omitted if the comment is at the beginning of a code block\). ## Declaration Comments are Side-By-Side When documenting the arguments for procedures and the members of structures, place the comments on the same lines as the declarations. Figures 3 and 4 show comments for procedure arguments and Figure 6 shows a simple structure declaration. The format for comments is the same in both cases. Place the comments to the right of the declarations, with all the left edges of all the comments lined up. When a comment requires more than one line, indent the additional lines to the same level as the first line, with the closing \*/ on the same line as the end of the text. For structure declarations it is usually useful to have a block of comments preceding the declaration, as in Figure 6. This comments before the declaration use the format given in Section 5.2. ![Figure 6. Use side-by-side comments when declaring structure](../assets/247fig6.png) members and procedure arguments. Declaration comments should normally begin in the 33rd column \(i.e. where you would be after 32 spaces or 4 tabs\). ## Curly Braces: \{ Goes at the End of a Line Open curly braces should not \(normally\) appear on lines by themselves. Instead, they should be placed at the end of the preceding line. Close curly braces always appear as the first non-blank character on a line. Figure 5 shows how to use curly braces in statements such as if and while, and Figure 6 shows how curly braces should be used in structure declarations. If an if statement has an else clause then else appears on the same line as the preceding \} and the following \{. Close curly braces are indented to the same level as the outer code, i.e., four spaces less than the statements they enclose. The only cases where a \{ appears on a line by itself are the initial \{ for the body of a procedure \(see Figures 3 and 4\) or where a block is being started _without_ being the body of an if, do, for, while or switch construct. Always use curly braces around compound statements, even if there is only one statement in the block. Thus you shouldn't write code like if (filePtr->numLines == 0) return -1; but rather if (filePtr->numLines == 0) { return -1; } This approach makes code less dense, but it avoids potential mistakes when adding additional lines to an existing single-statement block. It also makes it easier to set breakpoints in a debugger, since it guarantees that each statement on is on a separate line and can be named individually. There is one exception to the rule about enclosing blocks in \{\}. For if statements with cascaded else if clauses, you may use a form like the following: if (strcmp(argv[1], "delete") == 0) { ... } else if (strcmp(argv[1], "get") == 0) { ... } else if (strcmp(argv[1], "set") == 0) { ... } else { ... } ## Continuation Lines are Indented 8 Spaces You should use continuation lines to make sure that no single line exceeds 80 characters in length. Continuation lines should be indented 8 spaces so that they won't be confused with an immediately-following nested block \(see Figure 7\). Pick clean places to break your lines for continuation, so that the continuation doesn't obscure the structure of the statement. For example, if a procedure call requires continuation lines, make sure that each argument is on a single line. If the test for an if or while command spans lines, try to make each line have the same nesting level of parentheses if possible. I try to start each continuation line with an operator such as \*, &&, or \|\|; this makes it clear that the line is a continuation, since a new statement would never start with such an operator. ![Figure 7. Continuation lines are indented 8 spaces.](../assets/247fig7.png) ## Avoid Macros Except for Simple Things \#define statements provide a fine mechanism for specifying constants symbolically, and you should always use them instead of embedding specific numbers in your code. However, it is generally a bad idea to use macros for complex operations; procedures are almost always better \(for example, you can set breakpoints inside procedures but not in the middle of macros\). The only time that it is OK to use \#define's for complex operations is if the operations are critical to performance and there is no other way to get the performance \(have you measured the performance before and after to be sure it matters?\). When defining macros, remember always to enclose the arguments in parentheses: #define Min(a,b) (((a) < (b)) ? (a) : (b)) Otherwise, if the macro is invoked with a complex argument such as a\*b or small\|\|red it may result in a parse error or, even worse, an unintended result that is difficult to debug. # Documenting Code The purpose of documentation is to save time and reduce errors. Documentation is typically used for two purposes. First, people will read the documentation to find out how to use your code. For example, they will read procedure headers to learn how to call the procedures. Ideally, people should have to learn as little as possible about your code in order to use it correctly. Second, people will read the documentation to find out how your code works internally, so they can fix bugs or add new features; again, good documentation will allow them to make their fixes or enhancements while learning the minimum possible about your code. More documentation isn't necessarily better: wading through pages of documentation may not be any easier than deciphering the code. Try to pick out the most important things that will help people to understand your code and focus on these in your documentation. ## Document Things with Wide Impact The most important things to document are those that affect many different pieces of a program. Thus it is essential that every procedure interface, every structure declaration, and every global variable be documented clearly. If you haven't documented one of these things it will be necessary to look at all the uses of the thing to figure out how it's supposed to work; this will be time-consuming and error-prone. On the other hand, things with only local impact may not need much documentation. For example, in short procedures I don't usually have comments explaining the local variables. If the overall function of the procedure has been explained, and if there isn't much code in the procedure, and if the variables have meaningful names, then it will be easy to figure out how they are used. On the other hand, for long procedures with many variables I usually document the key variables. Similarly, when I write short procedures I don't usually have any comments in the procedure's code: the procedure header provides enough information to figure out what is going on. For long procedures I place a comment block before each major piece of the procedure to clarify the overall flow through the procedure. ## Don't Just Repeat What's in the Code The most common mistake I see in documentation \(besides it not being there at all\) is that it repeats what is already obvious from the code, such as this trivial \(but exasperatingly common\) example: /* * Increment i. */ i += 1; Documentation should provide higher-level information about the overall function of the code, helping readers to understand what a complex collection of statements really means. For example, the comment /* * Probe into the hash table to see if the symbol exists. */ is likely to be much more helpful than /* * Mask off all but the lower 8 bits of x, then index into table * t, then traverse the list looking for a character string * identical to s. */ Everything in this second comment is probably obvious from the code that follows it. Another thing to consider in your comments is word choice. Use different words in the comments than the words that appear in variable or procedure names. For example, the comment /* * VmMapPage -- * * Map a page. * ... which appears in the header for the Sprite procedure VmMapPage, doesn't provide any new information. Everything in the comment is already obvious from the procedure's name. Here is a much more useful comment: /* * VmMapPage -- * * Make the given physical page addressable in the kernel's * virtual address space. This procedure is used when the * kernel needs to access a user's page. * ... This comment tells why you might want to use the procedure, in addition to what it does, which makes the comment much more useful. ## Document Each Thing in Exactly One Place Systems evolve over time. If something is documented in several places, it will be hard to keep the documentation up to date as the system changes. Instead, try to document each major design decision in exactly one place, as near as possible to the code that implements the design decision. For example, put the documentation for each structure right next to the declaration for the structure, including the general rules for how the structure is used. You need not explain the fields of the structure again in the code that uses the structure; people can always refer back to the structure declaration for this. The principal documentation for each procedure goes in the procedure header. There's no need to repeat this information again in the body of the procedure \(but you might have additional comments in the procedure body to fill in details not described in the procedure header\). If a library procedure is documented thoroughly in a manual entry, then I may make the header for the procedure very terse, simply referring to the manual entry. For example, I use this terse form in the headers for all Tcl command procedures, since there is a separate manual entry describing each command. The other side of this coin is that every major design decision needs to be documented at least once. If a design decision is used in many places, it may be hard to pick a central place to document it. Try to find a data structure or key procedure where you can place the main body of comments; then reference this body in the other places where the decision is used. If all else fails, add a block of comments to the header page of one of the files implementing the decision. ## Write Clean Code The best way to produce a well-documented system is to write clean and simple code. This way there won't be much to document. If code is clean, it means that there are a few simple ideas that explain its operation; all you have to do is to document those key ideas. When writing code, ask yourself if there is a simple concept behind the code. If not, perhaps you should rethink the code. If it takes a lot of documentation to explain a piece of code, it is a sign that you haven't found an elegant solution to the problem. ## Document As You Go It is extremely important to write the documentation as you write the code. It's very tempting to put off the documentation until the end; after all, the code will change, so why waste time writing documentation now when you'll have to change it later? The problem is that the end never comes - there is always more code to write. Also, the more undocumented code that you accumulate, the harder it is to work up the energy to document it. So, you just write more undocumented code. I've seen many people start a project fully intending to go back at the end and write all the documentation, but I've never seen anyone actually do it. If you do the documentation as you go, it won't add much to your coding time and you won't have to worry about doing it later. Also, the best time to document code is when the key ideas are fresh in your mind, which is when you're first writing the code. When I write new code, I write all of the header comments for a group of procedures before I fill in any of the bodies of the procedures. This way I can think about the overall structure and how the pieces fit together before getting bogged down in the details of individual procedures. ## Document Tricky Situations If code is non-obvious, meaning that its structure and correctness depend on information that won't be obvious to someone reading it for the first time, be sure to document the non-obvious information. One good indicator of a tricky situation is a bug. If you discover a subtle property of your program while fixing a bug, be sure to add a comment explaining the problem and its solution. Of course, it's even better if you can fix the bug in a way that eliminates the subtle behavior, but this isn't always possible. # Testing One of the environments where Tcl works best is for testing. If all the functionality of an application is available as Tcl commands, you should be able to write Tcl scripts that exercise the application and verify that it behaves correctly. For example, Tcl contains a large suite of tests that exercise nearly all of the Tcl functionality. Whenever you write new code you should write Tcl test scripts to go with that code and save the tests in files so that they can be re-run later. Writing test scripts isn't as tedious as it may sound. If you're developing your code carefully you're already doing a lot of testing; all you need to do is type your test cases into a script file where they can be re-used, rather than typing them interactively where they vanish into the void after they're run. ## Basics Tests should be organized into script files, where each file contains a collection of related tests. Individual tests should be based on the procedure test, just like in the Tcl and Tk test suites. Here are two examples: test expr-3.1 {floating-point operators} { expr 2.3*.6 } 1.38 test expr-3.2 {floating-point operators} { list [catch {expr 2.3/0} msg] $msg } {1 {divide by zero}} test is a procedure defined in a script file named defs, which is sourced by each test file. The **test** command takes four arguments: a test identifier, a string describing the test, a test script, and the expected result of the script. test evaluates the script and checks to be sure that it produces the expected result. If not, it prints a message like the following: ==== expr-3.1 floating-point operators ==== Contents of test case: expr 2.3*.6 ==== Result was: 1.39 ---- Result should have been: 1.38 ---- expr-2.1 FAILED To run a set of tests, you start up the application and source a test file. If all goes well no messages appear; if errors are detected, a message is printed for each one. The test identifier, such as expr-3.1, is printed when errors occur. It can be used to search a test script to locate the source for a failed test. The first part of the identifier, such as expr, should be the same as the name of the test file, except that the test file should have a .test extension, such as expr.test. The two numbers allow you to divide your tests into groups. The tests in a particular group \(e.g., all the expr-3.n tests\) relate to a single sub-feature, such as a single C procedure or a single option of a Tcl command. The tests should appear in the test file in the same order as their numbers. The test name, such as floating-point operators, is printed when errors occur. It provides human-readable information about the general nature of the test. Before writing tests I suggest that you look over some of the test files for Tcl and Tk to see how they are structured. You may also want to look at the README files in the Tcl and Tk test directories to learn about additional features that provide more verbose output or restrict the set of tests that are run. Although it is possible to automatically generate names for tests, this is not recommended because it makes it difficult to search for the specific test in the test suite if all you have to go on is the test name. ## Organizing Tests Organize your tests to match the code being tested. The best way to do this is to have one test file for each source code file, with the name of the test file derived from the name of the source file in an obvious way \(e.g. textWind.test contains tests for the code in tkTextWind.c\). Within the test file, have one group of tests for each procedure \(for example, all the textWind-2.n tests in textWind.test are for the procedure TkTextWindowCmd\). The order of the tests within a group should be the same as the order of the code within the procedure. This approach makes it easy to find the tests for a particular piece of code and add new tests as the code changes. The Tcl test suite was written a long time ago and uses a different style where there is one file for each Tcl command or group of related commands, and the tests are grouped within the file by sub-command or features. In this approach the relationship between tests and particular pieces of code is much less obvious, so it is harder to maintain the tests as the code evolves. I don't recommend using this approach for new tests. ## Coverage When writing tests, you should attempt to exercise every line of source code at least once. There will be occasionally be code that you can't exercise, such as code that exits the application, but situations like this are rare. You may find it hard to exercise some pieces of code because existing Tcl commands don't provide fine enough control to generate all the possible execution paths \(for example, at the time I wrote the test suite for Tcl's dynamic string facility there were very few Tcl commands using the facility; some of the procedures were not called at all\). In situations like this, write one or more new Tcl commands just for testing purposes. For example, the file tclTest.c in the Tcl source directory contains a command testdstring, which provides a number of options that allow all of the dynamic string code to be exercised. tclTest.c is only included in a special testing version of tclsh, so the testdstring command isn't present in normal Tcl applications. Use a similar approach in your own code, where you have an extra file with additional commands for testing. It's not sufficient just to make sure each line of code is executed by your tests. In addition, your tests must discriminate between code that executes correctly and code that isn't correct. For example, write tests to make sure that the then and else branches of each if statement are taken under the correct conditions. For loops, run different tests to make the loop execute zero times, one time, and two or more times. If a piece of code removes an element from a list, try cases where the element to be removed is the first element, last element, only element, and neither first element nor last. Try to find all the places where different pieces of code interact in unusual ways, and exercise the different possible interactions. ## Memory Allocation Tcl and Tk use a modified memory allocator that checks for several kinds of memory allocation errors, such as freeing a block twice, failing to free a block, or writing past the end of a block. In order to use this allocator, don't call malloc, free, or realloc directly. Call ckalloc instead of malloc, ckfree instead of free, and ckrealloc instead of realloc. These procedures behave identically to malloc, free, and realloc except that they monitor memory usage. Ckalloc, ckfree, and ckrealloc are actually macros that can be configured with a compiler switch: if TCL\_MEM\_DEBUG is defined, they perform the checks but run more slowly and use more memory; if TCL\_MEM\_DEBUG is not defined, then the macros are just \#defined to malloc, free, and realloc so there is no penalty in efficiency. I always run with TCL\_MEM\_DEBUG in my development environment and you should too. Official releases typically do not have TCL\_MEM\_DEBUG set. If you set TCL\_MEM\_DEBUG anywhere in your code then you must set it everywhere \(including the Tcl and Tk libraries\); the memory allocator will get hopelessly confused if a block of memory is allocated with malloc and freed with ckfree, or allocated with ckalloc and freed with free. There is nothing equivalent to calloc in the debugging memory allocator. If you need a new block to be zeroed, call memset to clear its contents. If you compile with TCL\_MEM\_DEBUG, then an additional Tcl command named memory will appear in your application \(assuming that you're using the standard Tcl or Tk main program\). The memory command has the following options: **memory active** _file_ > Dumps a list of all allocated blocks \(and where they were allocated\) to _file_. Memory leaks can be tracked down by comparing dumps made at different times. **memory break\_on\_malloc** _number_ > Enter the debugger after _number_ calls to **ckalloc**. **memory info** > Prints a report containing the total allocations and frees since Tcl began, the number of blocks currently allocated, the number of bytes currently allocated, and the maximum number of blocks and bytes allocated at any one time. **memory init** _onoff_ > If _onoff_ is on, new blocks of memory are initialized with a strange value to help locate uninitialized uses of the block. Any other value for _onoff_ turns initialization off. Initialization is on by default. **memory trace** _onoff_ > If _onoff_ is on, one line will be printed to stderr for each call to **ckalloc**. Any other value for _onoff_ turns tracing off. Tracing is off by default. **memory trace\_on\_at\_malloc** _number_ > Arranges for tracing to be turned on after _number_ calls to **ckalloc**. **memory validate** _onoff_ > If _onoff_ is on, guard zones around every allocated block are checked on every call to **ckalloc** or **ckfree** in order to detect memory overruns as soon as possible. If _onoff_ is anything other than on, checks are made only during **ckfree** calls and only for the block being freed. Memory validation has a very large performance impact, so it is off by default. The debugging memory allocator is inferior in many ways to commercial products like Purify, so its worth using one of the commercial products if possible. Even so, please use **ckalloc** and **ckfree** everywhere in your code, so that other people without access to the commercial checkers can still use the Tcl debugging allocator. ## Fixing Bugs Whenever you find a bug in your code it means that the test suite wasn't complete. As part of fixing the bug, you should add new tests that detect the presence of the bug. I recommend writing the tests after you've located the bug but before you fix it. That way you can verify that the bug happens before you implement the fix and goes away afterwards, so you'll know you've really fixed something. Use bugs to refine your testing approach: think about what you might be able to do differently when you write tests in the future to keep bugs like this one from going undetected. ## Tricky Features I also use tests as a way of illustrating the need for tricky code. If a piece of code has an unusual structure, and particularly if the code is hard to explain, I try to write additional tests that will fail if the code is implemented in the obvious manner instead of using the tricky approach. This way, if someone comes along later, doesn't understand the documentation for the code, decides the complex structure is unnecessary, and changes the code back to the simple \(but incorrect\) form, the test will fail and the person will be able to use the test to understand why the code needs to be the way it is. Illustrative tests are not a substitute for good documentation, but they provide a useful addition. ## Test Independence Try to make tests independent of each other, so that each test can be understood in isolation. For example, one test shouldn't depend on commands executed in a previous test. This is important because the test suite allows tests to be run selectively: if the tests depend on each other, then false errors will be reported when someone runs a few of the tests without the others. For convenience, you may execute a few statements in the test file to set up a test configuration and then run several tests based on that configuration. If you do this, put the setup code outside the calls to the test procedure so it will always run even if the individual tests aren't run. I suggest keeping a very simple structure consisting of setup followed by a group of tests. Don't perform some setup, run a few tests, modify the setup slightly, run a few more tests, modify the setup again, and so on. If you do this, it will be hard for people to figure out what the setup is at any given point and when they add tests later they are likely to break the setup. # Porting Issues The X Window System, ANSI C, and POSIX provide a standard set of interfaces that make it possible to write highly portable code. However, some additional work will still be needed if code is to port among all of the UNIX platforms. As Tcl and Tk move from the UNIX world onto PCs and Macintoshes, porting issues will become even more important. This section contains a few tips on how to write code that can run on many different platforms. ## Stick to Standards The easiest way to make your code portable is to use only library interfaces that are available everywhere \(or nearly everywhere\). For example, the ANSI C library procedures, POSIX system calls, and Xlib windowing calls are available on many platforms; if you code to these standards your packages will be quite portable. Avoid using system-specific library procedures, since they will introduce porting problems. ## Minimize \#ifdefs Although there will be situations where you have to do things differently on different machines, \#ifdefs are rarely the best way to deal with these problems. If you load up your code with \#ifdef statements based on various machines and operating systems, the code will turn into spaghetti. \#ifdefs make code unreadable: it is hard to look at \#ifdef-ed code and figure out exactly what will happen on any one machine. Furthermore, \#ifdefs encourage a style where lots of machine dependencies creep all through the code; it is much better to isolate machine dependencies in a few well-defined places. Thus you should almost never use \#ifdefs. Instead, think carefully about the ways in which systems differ and define procedural interfaces to the machine-dependent code. Then provide a different implementation of the machine-dependent procedures for each machine. When linking, choose the version appropriate for the current machine. This way all of the machine dependencies for a particular system are located in one or a few files that are totally separate from the machine-dependent code for other systems and from the main body of your code. The only "conditional" code left will be the code that selects which version to link with. You won't be able to eliminate \#ifdefs completely, but please avoid them as much as possible. If you end up with code that has a lot of \#ifdefs, this should be a warning to you that something is wrong. See if you can find a way to re-organize the code \(perhaps using the techniques described later in this section\) to reduce the number of \#ifdefs. ## Organize by Feature, Not by System Don't think about porting issues in terms of specific systems. Instead, think in terms of specific features that are present or absent in the systems. For example, don't divide your code up according to what is needed in HP-UX versus Solaris versus Windows. Instead, consider what features are present in the different systems; for example, some systems have a waitpid procedure, while others don't yet provide one, and some systems have ANSI C compilers that support procedure prototypes, while some systems do not. The feature-based approach has a number of advantages over the system-based approach. First, many systems have features in common, so you can share feature-based porting code among different systems. Second, if you think in terms of features then you can consider each feature separately \("what do I do if there is no waitpid?"\); this replaces one large problem with several smaller problems that can be dealt with individually. Lastly, the autoconf program can be used to check for the presence or absence of particular features and configure your code automatically. Once you've gotten your code running on several different systems, you'll find that many new systems can be handled with no additional work: their features are similar to those in systems you've already considered, so autoconf can handle them automatically. ## Use Emulation One of the cleanest ways to handle porting problems is with emulation: assume the existence of certain procedures, such as those in the POSIX standard, and if they don't exist on a given system then write procedures to emulate the desired functionality with the facilities that are present on the system. For example, when Tcl first started being used widely I discovered that many systems did not support the waitpid kernel call, even though it was part of the POSIX standard. So, I wrote a waitpid procedure myself, which emulated the functionality of waitpid using the wait and wait3 kernel calls. The best way to emulate waitpid was with wait3, but unfortunately wait3 wasn't available everywhere either, so the emulation worked differently on systems that had wait3 and those that supported only wait. The autoconf program checks to see which of the kernel calls are available, includes the emulation for waitpid if it isn't available, and sets a compiler flag that indicates to the emulation code whether or not wait3 is available. You can also emulate using \#defines in a header file. For example, not all systems support symbolic links, and those that don't support symbolic links don't support the lstat kernel call either. For these systems Tcl uses stat to emulate lstat with the following statement in tclUnix.h: #define lstat stat If a header file is missing on a particular system, write your own version of the header file to supply the definitions needed by your code. Then you can \#include your version in your code if the system doesn't have a version of its own. For example, here is the code in tclUnix.h that handles unistd.h, which isn't yet available on all UNIX systems: #ifdef HAVE_UNISTD_H #include <unistd.h> #else #include "compat/unistd.h" #endif The configure script generated by autoconf checks for the existence of unistd.h in the system include directories and sets HAVE\_UNISTD\_H if it is present. If it isn't present, tclUnix.h includes a version from the Tcl source tree. ## Use Autoconf The GNU autoconf program provides a powerful way to configure your code for different systems. With autoconf you write a script called configure.in that describes the porting issues for your software in terms of particular features that are needed and what to do if they aren't present. Before creating a release of your software you run autoconf, which processes configure.in and generates a shell script called configure. You then include configure with your distribution. When it is time to install the distribution on a particular system, the installer runs the configure script. configure pokes around in the system to find out what features are present, then it modifies the Makefile accordingly. The modifications typically consist of compiling additional files to substitute for missing procedures, or setting compiler flags that can be used for conditional compilation in the code. Use of libtool is not recommended; it tends to inhibit porting to anything other than fairly conventional UNIX platforms. ## Porting Header File In spite of all the above advice, you will still end up needing some conditional compilation, for example to include alternate header files where standard ones are missing or to \#define symbols that aren't defined on the system. Put all of this code in the porting header file for the package, then \#include this header file in each of the source files of the package. With this approach you only need to change a single place if you have to modify your approach to portability, and you can see all of the porting issues in one place. You can look at tclPort.h and tkPort.h for examples of porting header files. # Miscellaneous ## Changes Files Each package should contain a file named changes that keeps a log of all significant changes made to the package. The changes file provides a way for users to find out what's new in each new release, what bugs have been fixed, and what compatibility problems might be introduced by the new release. The changes file should be in chronological order. Just add short blurbs to it each time you make a change. Here is a sample from the Tk changes file: 5/19/94 (bug fix) Canvases didn't generate proper Postscript for stippled text. 5/20/94 (new feature) Added "bell" command to ring the display's bell. 5/26/94 (feature removed) Removed support for "fill" justify mode from Tk_GetJustify and from the TK_CONFIG_JUSTIFY configuration option. None of the built-in widgets ever supported this mode anyway. *** POTENTIAL INCOMPATIBILITY *** The entries in the changes file can be relatively terse; once someone finds a change that is relevant, they can always go to the manual entries or code to find out more about it. Be sure to highlight changes that cause compatibility problems, so people can scan the changes file quickly to locate the incompatibilities. _\(The Tcl and Tk core additionally uses a ChangeLog file that has a much higher detail within it. This has the advantage of having more tooling support, but tends to be so verbose that the shorter summaries in the changes file are still written up by the core maintainers before each release.\)_ # Copyright This document has been placed in the public domain. |
Name change from tip/248.tip to tip/248.md.
|
| < | < | | | | | | | | | > | | | | | | | | | | | | | | | | | | > | 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 | # TIP 248: Integrate Tile into Tk as Ttk Author: Jeff Hobbs <[email protected]> Author: Donal K. Fellows <[email protected]> State: Final Type: Project Vote: Done Created: 08-Jun-2005 Post-History: Tcl-Version: 8.5 Obsoletes: 172 ----- # Abstract This TIP proposes that the tile themed widget set be integrated into Tk from 8.5 onwards as the static package Ttk. # Rationale It is well known that Tk has been lacking in graphical glitz for a few years; GUI standards have moved on whereas Tk has remained largely static. The core of Tk is still great \(e.g. its resizing behaviour is second to none\) but fancy shaded buttons are what modern users expect. Through the sterling work of Joe English and others, the Tile package is available which offers a new set of widgets for use on top of the Tk foundation, and which provide that extra graphical polish by leveraging underlying graphics layers \(e.g. the Luna theming engine on Windows XP, the Aqua theming on MacOSX, etc.\) This is _exactly_ what we need, so we should ensure that every user of Tk can take advantage of these new capabilities \(universality is important\) through updating our distribution strategy. This TIP acknowledges that Tile is a project that is still in development, but the current state is stable enough for inclusion and will encourage wider use. It is expected that more changes will come later. This TIP proposes integration of Tile into the Tk core as the Ttk package. It would be part of the standard core, but have a version different from the overarching Tk \(much as Tcl has the http package\). This will allow for minor user-level changes and continued rapid development as part of the larger Tk framework \(eg, Tk patchlevel releases can have minor version bumps to the Ttk package\). Note that although the Tile widgets are _mostly_ drop-in replacements for the Tk core widgets, they are not perfect stand-ins due to the differences in the way state is managed. This means that this TIP categorically does not propose the replacement of Tk's widgets with Tile's. # Proposed Changes 1. Full integration of the Tile package into the Tk source tree. This would include renaming of source files to fit inside the Tk directory structure. A static package named Ttk will signify their availability and specific version. 2. To facilitate mixing of widgets between Tk and Tile, all Tk's widget creation commands are to be _additionally_ declared in the **::tk** namespace and [**namespace export**]ed from there. Allowing users to mix class Tk and themed Ttk widgets improves the overall richness and flexibility of Tk applications. # Discussion See the discussion in the thread at <http://aspn.activestate.com/ASPN/Mail/Message/tcl-core/2761205.> Tile is expected to continue as an 8.4-compatible package while 8.4 is still the standard stable version. # Copyright This document has been placed in the public domain. |
Name change from tip/249.tip to tip/249.md.
|
| < | < | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 249: Unification of Tcl's Parsing of Numbers Author: Kevin B. Kenny <[email protected]> Author: David S. Cargo <[email protected]> Author: Don Porter <[email protected]> State: Draft Type: Informative Vote: No voting Created: 13-Jun-2005 Post-History: ----- # Abstract This TIP proposes to unify the recognition of all of Tcl's "numeric" objects into a single parser. The intended effect is to improve performance by eliminating a number of cases where a cached numeric representation may be discarded, and to restore \(more accurately, to establish\) the "everything is a string" principle in dealing with numbers. # Rationale Tcl's handling of numbers has always been problematic and ambiguous. Even in the earliest releases of the **expr** command, there were issues with the unexpected demotion of floating point numbers to integers, causing subsequent divisions to be interpreted as integer division with incorrect results. Another trouble spot has been the interpretation of constants with leading zeroes. When these are interpreted as integers, they are octal numbers. They can also be interpreted as floating point constants \(at least with _Tcl\_GetDoubleFromObj_\), in which case they are decimal. Because of this ambiguity, the **expr** system cannot make effective use of the internal representation of a floating point number; it needs to refer back to the string to make sure that the number is not an octal integer to which _Tcl\_GetDoubleFromObj_ has been applied. Even more confusing is the treatment of numbers that have leading zeroes but contain the digits 8 or 9. These are rejected by the **expr** parser as invalid octal but are accepted by _Tcl\_GetDoubleFromObj_. # Proposal This TIP proposes a strict "everything is a string" interpretation for strings as numeric values. The set of strings that can be interpreted as numbers shall be partitioned into disjoint subsets, with a single "canonical" representation for each. This change will imply that a few C calls will break compatibility. In particular, _Tcl\_GetDoubleFromObj_ may leave an integer internal representation in the object, despite the documentation's assertion that the object will shimmer. Similarly, _Tcl\_GetDoubleFromObj_ will no longer interpret octal integers as decimal; this feature causes only surprise and consternation. The _Tcl\_ConvertToType_ call will also no longer force conversion to a specific numeric type. Since it does not do so, it is not reasonable for extensions to use it on the numeric types. For this reason, the numeric types _shall not be registered;_ _Tcl\_GetObjType_ will fail when presented with one of their names. When one of the conversion procedures _Tcl\_GetIntFromObj_, _Tcl\_GetWideIntFromObj_, _Tcl\_GetBignumFromObj_ \(assuming the eventual approval of [[237]](237.md)\), or _Tcl\_GetDoubleFromObj_ is called, it will cast any pre-existing numeric internal representation that it finds to the appropriate return type \(throwing an error if the number is too large to represent, or a double is used in an integer context\). If the procedure finds no pre-existing numeric internal representation, it will extract the string representation, determine its canonical representation as a number, and store that. The easiest way to visualize the specific sets of strings that are recognized as numbers is with a diagram of the state machine that implements them. ![State machine that recognizes numbers.](../assets/249statemachine.png) In the diagram, "Start" represents the start state of the machine. The leading and trailing whitespace that is allowed for all numbers is not diagrammed, for clarity. Intermediate states of the machine are represented by small ovals. Large rectangles represent final states, and are labeled with the type of number that will result. Note that any number can optionally begin with a '\+' or '-' character, which will not be mentioned further. Each of the accepting states, however, merits further discussion. 1. The string "0" shall always represent an integer of the smallest type available \(**tclIntType**\). It shall never represent a floating point value. 2. A leading zero followed by a string of octal digits shall be interpreted as an octal integer. The integer shall be stored in the smallest of **tclIntType**, **tclWideIntType** and **tclBignumType** that will hold it. \(Note that storing **tclBignumType** is possible without accepting [[237]](237.md), provided that the _Tcl\_Get\*FromObj_ routines recognize it and convert its value as needed.\) The interpretation as an octal integer shall hold even if the string is presented to _Tcl\_GetDoubleFromObj_, which today interprets it as decimal. 3. A leading zero, followed by the letter 'X' \(case insensitive\) and a string of hexadecimal digits shall be interpreted as a hexadecimal integer. Again, the smallest representation needed is chosen. 4. A string of decimal digits beginning with a nonzero digit is interpreted as a decimal integer and stored in the smallest suitable internal representation. 5. A string of digits beginning with a zero but containing the digits **8** or **9** is an error; it appears to be bad octal. It would be possible to allow this case in _Tcl\_GetDoubleFromObj_, but it seems unwise, since the consequence would be that **string is double** would accept "double" strings that will fail in **expr**. 6. A string consisting of a nonempty sequence of decimal digits and a single period \(which may appear anywhere within the string\) is a valid floating point constant in 'F' format, even if it begins with '0'. It is interpreted in decimal and stored in a **tclDoubleType**. If the input number is too small to represent, an appropriately signed zero is stored. If the input number is too large to represent, an appropriately signed infinity is stored. 7. Floating point numbers in the usual 'E' format are accepted and interpreted in decimal. Once again, they are stored in **tclDoubleType** and are replaced with zero or infinity if they are too small or large. 8. The constants, "Inf", and "Infinity" \(perhaps with a leading signum\) are interpreted as infinities. Infinity is represented as **tclDoubleType.** 9. The constant "NaN" is the IEEE "Not a Number" value. It is specifically permitted in the parser so that **binary format q NaN** and similar calls can produce NaN on an external medium. The presence of NaN in expressions, or in _Tcl\_GetDoubleFromObj_, signals an error. NaN is represented as **tclDoubleType**. 10. IEEE floating point does not have a single unique NaN value, so a NaN may be augmented by a parenthesized string of hexadecimal digits, which will be stored in its least significant bits. It shall not be possible to construct signalling NaN by this route; only quiet NaN will be supported. NaN is represented as **tclDoubleType.** # Additions In addition to the base state machine detailed above, the state machine of the reference implementation contains additional states to parse integer values beginning with the **0b** or **0o** prefixes as originally proposed in [[114]](114.md). Getting these prefixes recognized in Tcl 8.5 is an important migration step to support migration to whatever version of Tcl drops the "leading **0** implies octal format" rule. Also in addition, the parsing routine will accept a _flags_ value containing the flag bits below that exert finer control on the parsing. These extra controls were found to be required to permit the [scan] command to use the same parser. * **TCL\_PARSE\_INTEGER\_ONLY** -- accept only integer values; reject strings that denote floating point values \(or accept only the leading portion of them that are integer values\). * **TCL\_PARSE\_SCAN\_PREFIXES** -- ignore the prefixes **0b** and **0o** that are not part of the [scan] command's vocabulary. Use only in combination with **TCL\_PARSE\_INTEGER\_ONLY**. * **TCL\_PARSE\_OCTAL\_ONLY** - parse only in the octal format, whether or not a prefix is present that would lead to octal parsing. Use only in combination with **TCL\_PARSE\_INTEGER\_ONLY**. * **TCL\_PARSE\_HEXADECIMAL\_ONLY** - parse only in the hexadecimal format, whether or not a prefix is present that would lead to hexadecimal parsing. Use only in combination with **TCL\_PARSE\_INTEGER\_ONLY**. * **TCL\_PARSE\_DECIMAL\_ONLY** - parse only in the decimal format, no matter whether a **0** prefix would normally force a different base. # Incompatibilities The change described is sufficient to run the Tcl and Tk test suites with unwanted test results only in the detailed format of error messages for integer overflow and in the types returned by using the **testobj** command \(not part of the usual distribution\) to introspect them. Despite this reassurance, several potential incompatibilities are identified. First, as mentioned above, C extensions will no longer have fine control over Tcl's built-in numeric types, because the types will not be registered and hence will be unavailable for use with _Tcl\_ConvertToType._ This is actually a good thing, since it means that the rest of Tcl can assume that they are well-behaved, resulting in a considerable simplification. Most of the Tcl Core Team believes that _Tcl\_ConvertToType_ has no legitimate use in any case. Second, it will no longer be correct to assume that _Tcl\_Get\*FromObj_ will leave an internal representation of precisely the requested type. It is, in any case, a highly questionable practice for callers to assume a specific internal representation \(with the possible exception of Tcl\_Set\*Obj and Tcl\_New\*Obj\). There will no doubt be a few extensions that run afoul of this change, but they can be fixed easily in such a way that they will continue to compile and run on earlier versions of Tcl. Third, _Tcl\_GetDoubleFromObj_ will be both more and less permissive than before. It will no longer accept constants with a leading zero and no decimal point or 'E' that are invalid octal numbers. On the other hand, it will accept constants that are too large to fit in a **Tcl\_WideInt**; somewhat surprisingly, **string repeat 9 50** cannot today be interpreted as a double. **string is double** will follow _Tcl\_GetDoubleFromObj_ in what it considers acceptable. Any string that is accepted as either an integer or a double by **expr** will be accepted in _Tcl\_GetDoubleFromObj_, and only those strings will be accepted. Fourth, the recognition of **0b** and **0o** as valid prefixes for integer values is a type of incompatibility. # Reference Implementation See [[237]](237.md) for more implementation details. # Copyright Copyright \(c\) 2005 by Kevin B. Kenny. All rights reserved. This document may be distributed subject to the terms and conditions set forth in the Open Publication License, version 1.0 <http://www.opencontent.org/openpub/> . |
Name change from tip/25.tip to tip/25.md.
|
| < | < | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 25: Native tk_messageBox on Macintosh Author: Mats Bengtsson <[email protected]> State: Withdrawn Type: Project Tcl-Version: 8.5 Vote: Pending Created: 07-Feb-2001 Obsoleted-By: 152 Post-History: ----- # Abstract This is a replacement for the _tk\_messageBox_ on the Macintosh with a native implementation which is compliant with the Appearance Manager in Mac OS 8 and later. # Rationale The present \(in 8.3.2p1 and earlier\) _tk\_messageBox_ on the Macintosh is non-movable, and lacks many features that are required to be compliant with Mac OS 8 and later. Non-movable dialogs should be abandoned in a multitasking environment. This TIP presents a step to extend the native appearance on the Macintosh. ![This is the present tk_messageBox.](../assets/25original.gif) ![{} {} This is the native tk_messageBox.](../assets/25native.gif) # Reference Implementation The proposed change is now implemented as a loadable extension \(in C\) on Macintosh, and can be downloaded at <http://hem.fyristorg.com/matben/download/MovableAlerts.sit> . This extension requires Tk 8.3.2p1 or later due to the changed stub loading mechanism. The core of the code should go in the _tkMacDialog.c_ file. Some additional changes are necessary in order to load the new _tk\_messageBox_ and not the old, script based _tk\_messageBox_. Also, need to check for the presence of the Appearance manager: if (Appearance Manager) use native (new) messageBox else use present script based messageBox All functionality from the documentation that are applicable are implemented, with some exceptions: * There is a _-finemessage_ option to support the native text message set in a smaller font below the main message. * Both _-message_ and _-finemessage_ option are truncated at 255 characters. * Buttons appear from right to left instead of vice versa. * There is always a default button. All these deviations are consistent with the look-and-feel of Mac OS 8.0 and on. Existing scripts using _tk\_messageBox_ are compatible with the new _tk\_messageBox_. Open questions: * Name of extra option _-finemessage_ * Name of the two C functions in the implementation * How to make the core code call the new code instead of the original, script implemented # Copyright This document has been placed in the public domain |
Name change from tip/250.tip to tip/250.md.
|
| < | < | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 250: Efficient Access to Namespace Variables Author: Will Duquette <[email protected]> Author: miguel sofer <[email protected]> State: Final Type: Project Vote: Done Created: 19-Jun-2005 Post-History: Tcl-Version: 8.5 ----- # Abstract This TIP proposes a new **namespace** subcommand, **namespace upvar**, to efficiently alias namespace variables into the current scope. # Rationale A pure-Tcl object system which defines a namespace to contain the variables for each object instance must either duplicate the object's method code in each instance namespace, or define the method code such that it exists in one namespace but accesses data from another. The Snit package <http://www.wjduquette.com/snit> does the latter. Instance variables are declared automatically within each method body using code like this, where "selfns" is a variable containing the name of the instance namespace: upvar ${selfns}::myvar myvar The fully-qualified variable name "$\{selfns\}::myvar" must be recomputed each time the method is called, which is a significant source of method-call overhead. This TIP proposes a mechanism for avoiding many of these costs while also allowing people to write clearer code. With **namespace upvar**, the code would look like this: namespace upvar $selfns myvar myvar The speed gains come from: * it avoids building and then destroying a Tcl\_Obj for the fully qualified name * it avoids parsing the fully qualified name into its namespace/tail components, creating and then destroying the corresponding Tcl\_Objs * it may reuse a cached namespace in the internal representation of $\{selfns\} In addition, the programmer's intention is easier to see in a command namespace upvar $selfns var1 var1 var2 var2 var3 var3 than in the currently necessary upvar 0 ${selfns}::var1 var1 ${selfns}::var2 var2 ${selfns}::var3 var3 where the fact that all variables come from the same namespace is not so obvious. # Specification The syntax of the new subcommand is as follows: > **namespace upvar** _ns otherVar myVar_ ?_otherVar myVar_ ...? The semantics are identical to the following **upvar** call: > **upvar 0** _ns_::_otherVar_ _myVar_ ?_ns_::_otherVar_ _myVar_...? That is, the variable _otherVar_ in namespace _ns_ \(as resolved from the local scope\) is aliased to variable _myVar_ in the local scope. # Reference Implementation A reference implementation of **namespace upvar** is being developed at SF patch \#1275435 <https://sourceforge.net/tracker/index.php?func=detail&aid=1275435&group_id=10894&atid=310894> . # Copyright This document has been placed in the public domain. |
Name change from tip/251.tip to tip/251.md.
|
| < | < | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 251: Enhance the 'list' Command Author: Brian Schmidt <[email protected]> Author: Sérgio Loureiro <[email protected]> State: Rejected Type: Project Vote: Done Created: 28-Jun-2005 Post-History: Tcl-Version: 8.6 ----- # Abstract This TIP proposes enhancing the existing **list** command to serve as a top-level command ensemble for all the related list commands that have proliferated over time, as well as making it easier to add future new list-based commands. # Rationale There are numerous top-level commands for lists already. This command would centralize them, making it easier for new developers of Tcl scripts to learn all the related list commands, to simplify and reduce the number of top-level commands to learn, etc. The enhanced **list** would be consistent with the new top-level commands **chan** [[208]](208.md) and **dict** [[111]](111.md), as well as the existing **string** and **file** commands. # Specification A new command **list** will be added with the following syntax: list append: equivalent to **lappend** list create: equivalent to **list** list index: equivalent to **lindex** list insert: equivalent to **linsert** list join: equivalent to **join** list length: equivalent to **llength** list range: equivalent to **lrange** list repeat: equivalent to **lrepeat** \(see [[136]](136.md)\) list replace: equivalent to **lreplace** list search: equivalent to **lsearch** list set: equivalent to **lset** list sort: equivalent to **lsort** Each represents the existing command that is commented. The arguments to each would remain what the current command takes. Note that **split** is not included as it operates on a string and returns a list, and **concat** is not included because it can operate on both normal strings and lists. The old commands could then potentially be deprecated: * **join** * **lappend** * **lindex** * **linsert** * **llength** * **lrange** * **lrepeat** * **lreplace** * **lsearch** * **lset** * **lsort** # Incompatabilities Incompatability with the existing list command could potentially be solved by allowing the list command _without_ one of the defined options to be shorthand for the new **list create** command option. If the first argument to the new list command is not one of the new known options then **list create** is assumed by default. For example, list {my list} would be equivalent to: list set {my list} {} It appears the only existing scripts that would break would be those that actually utilize the **list** command, has at least 2 arguments, and have as their first argument one of the new list command's ensemble options. This would likely result in a small minority of scripts being impacted. Only Tcl code with lists defined _exactly_ as follows would break: list append ?arg... list create ?arg... list index ?arg... list insert ?arg... list join ?arg... list length ?arg... list range ?arg... list repeat ?arg... list replace ?arg... list search ?arg... list set ?arg... list sort ?arg... # Copyright This document has been placed in the public domain. |
Name change from tip/252.tip to tip/252.md.
|
| < | | < | | | | | | > | | | | | | | | | | | | | | | | > | 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 | # TIP 252: Add New 'string' Command Options Author: Brian Schmidt <[email protected]> Type: Project State: Rejected Vote: Done Created: 28-Jun-2005 Tcl-Version: 8.6 Post-History: ----- # Abstract This TIP proposes moving several existing string-related commands to be options in the existing top-level **string** command. # Rationale There is an existing top-level **string** command already. However, there are other existing top-level string-related commands that for consistency should be options in the existing **string** command. These additional string command options would further centralize all string-related commands, making it easier for new users to see all the related string commands. # Specification Additional **string** command options would be added utilizing existing top-level commands, using the following syntax: string split ;equivalent to split string format ;equivalent to format string scan ;equivalent to scan string subst ;equivalent to subst Each represents the existing command that is commented. The arguments to each would remain what the current command takes. The old commands could then potentially be eventually deprecated: split format scan subst # Copyright This document has been placed in the public domain. |
Name change from tip/253.tip to tip/253.md.
|
| < | | < | | | | | | > | | | | | | | | | | | | | > | 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 | # TIP 253: Consolidate Package-Related Commands Author: Brian Schmidt <[email protected]> Type: Project State: Draft Vote: Pending Created: 05-Jul-2005 Tcl-Version: 8.7 Post-History: ----- # Abstract This TIP proposes enhancing the existing **package** command with additional subcommands to serve as the top-level command container for the existing **pkg::create** and **pkg\_mkIndex** commands. # Rationale The **pkg::create** and **pkg\_mkIndex** commands, while they relate to packages, are their own separate top-level commands. For consistency, clarity and also making it easier for new users to see all the related options, those commands should become options under the existing **package** command. # Specification Additional **package** command options will be added with the following subcommand syntax: package create ;pkg::create package mkIndex ;pkg_mkIndex Each represents the existing command that is commented. The arguments to each would remain what the current command takes. The following old commands could then potentially be eventually deprecated: pkg::create pkg_mkIndex # Copyright This document has been placed in the public domain. |
Name change from tip/254.tip to tip/254.md.
|
| < | < | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 254: New Types for Tcl_LinkVar Author: Rene Meyer <[email protected]> State: Final Type: Project Vote: Done Created: 21-Jul-2005 Post-History: Tcl-Version: 8.5 ----- # Abstract Currently only a limited set of types of C variable may be linked to using Tcl\_LinkVar. This TIP proposes extending this to cover all the basic numeric C types. # Rationale With the current implementation it is not possible to link the following types directly to a Tcl variable, making it much more difficult to couple such variables to the Tcl level \(compared with **int** or **double** variables\). This TIP fixes this, making it easier to link C variables and embedded Tcl code. * **char** * **unsigned char** * **short** * **unsigned short** * **unsigned int** * **long** * **unsigned long** * **Tcl\_WideUInt** * **float** There will be no impact on current applications. # Specification The new types are inserted as new **\#define TCL\_LINK\_\*** statements in the _tcl.h_ header file and in the **switch** statements in the _Tcl\_Link_ functions. The documentation of _Tcl\_\*Link\*_ should mention the new types. # Reference Implementation A reference implementation is available as Patch \#1242844 on SourceForge<http://sf.net/support/tracker.php?aid=1242844> . # Copyright This document has been placed in the public domain. |
Name change from tip/255.tip to tip/255.md.
|
| < | < | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 255: Add 'min' and 'max' [expr] Functions Author: Jeff Hobbs <[email protected]> State: Final Type: Project Tcl-Version: 8.5 Vote: Done Created: 21-Jul-2005 Post-History: ----- # Abstract This TIP proposes enhancing the Tcl **expr** command with **min** and **max** functions. # Rationale Many programs need to find the minimum or maximum of a set of numbers, so having functions to do this will make many script programmers' lives easier. This will be adopting yet another feature from TclX, but with the minor enhancement of being able to handle arbitrary numbers of arguments. # Specification The **min** and **max** functions shall be created using Tcl commands \(in a namespace such all namespaces will pick them up by default\) in the new 8.5 **expr** function style \(see [[232]](232.md)\). They will take one or more numeric arguments \(of any valid numeric type\) and return the minimum or maximum value of those numbers \(depending on which function was invoked\). # Examples expr {min(0,3,1)} => 0 expr {max(4.2, 0xF, wide(1))} => 15.0 expr {min(4.2)} => 4.2 expr {min()} => too few arguments for math function # Reference Implementation [To be uploaded to SourceForge and URL added to this TIP.] # Copyright This document has been placed in the public domain. |
Name change from tip/256.tip to tip/256.md.
|
| < | < | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 256: Implement Tabular and Wordprocessor Style Tabbing Author: Vince Darley <[email protected]> Author: Vince Darley <[email protected]> State: Final Type: Project Vote: Done Created: 12-Aug-2005 Post-History: Tcl-Version: 8.5 ----- # Abstract There are two common style of tabbing in the computer world: that used for a regular table of information, and that used by a word-processor/text editor. This TIP proposes to add support for the latter to Tk's **text** widget. # Overview Tk's **text** widget has historically only supported a _tabular_ style of tabbing, where the n'th tab character is associated explicitly with the n'th tab stop \(irrespective of whether that stop is to the left or right of the current x-position - if that stop is to the left then a single space is inserted as a fallback\). A _wordprocessor_ \(or typewriter\) has a different style in which a tab character is associated with the next tab stop to the right of the current x-position. This TIP proposes to add wordprocessor-style tabbing to Tk's **text** widget. Tk 8.4 only supports tabular tabbing \(except for the special _-tabs \{\}_ case, which uses wordprocessor style 8-tabs!\), although none of this is clearly documented at all. Tk 8.5 at present actually only supports wordprocessor style tabbing \(and fixed a bunch of other bugs present in Tk 8.4's tab handling\). This behaviour change was an inadvertent result of fixing bugs in the code without the correct behaviour being very clearly specified. Hence this TIP will restore the old behaviour \(minus bugs\) as the default, and add the option of the new wordprocessor style behaviour. # Proposal A new **-tabstyle** configuration option will be added to the **text** widget, taking the values **wordprocessor** or **tabular** to specify the style of tabbing. The same option will also be added to **tags** in the text widget \(which, as usual, will also allow an empty value for the configuration option\). The default style of tabbing will be **tabular** for compatibility with Tk 8.4. Neither style name may be abbreviated. As a result of this change, abbreviations such as **-ta** or **-tab** will become ambiguous and trigger an error. This is considered a bug in the calling script \(and a trivial thing to fix in such scripts\). Similar ambiguities have been introduced by TIPs in the past \(e.g. with _grid_\). It may actually be a useful ambiguity, in that it will alert script writers to the fact that new tabbing functionality is available, and in particular that a decision on desired tab style needs to be made. In addition the strange difference in Tk 8.4 between an empty **-tabs** value and any other value will be changed for Tk 8.5 - it will use the **-tabstyle** option to determine how to interpret tabs under all circumstances, and use the **-tabs** list simply to determine the location of the tab stops. Here's an example usage: pack [text .t] .t configure -tabs {0.5i 1.0i 1.5i 2.0i 2.5i 3.0i 3.5i 4.0i 4.5i} .t insert end "a\tb\tc\tasdbcanasdasd\te\tf\tg\n" .t insert end "a\tb\tc\tasdbcanasdasd\te\tf\tg\n" .t insert end "a\tb\tc\tasdbcanasdasd\te\tf\tg\n" .t insert end "a\tb\tc\tasdbcanasdasd\te\tf\tg\n" .t insert end "a\tb\tc\tasdbcanasdasd\te\tf\tg\n" .t insert end "a\tb\tc\tasdbcanasdasd\te\tf\tg\n" .t insert end "a\tb\tc\tasdbcanasdasd\te\tf\tg\n" .t tag configure wordprocessor -tabstyle wordprocessor .t tag add wordprocessor 3.0 5.0 .t tag configure tabular -tabstyle tabular .t tag add tabular 5.0 7.0 and here's an example showing how Tk 8.4 does _not_ move you to the next tab stop to the right each time: pack [text .t] .t configure -tabs {0.25i} .t insert end "[string repeat a 20][string repeat \tb 10]" The above behaves completely differently in Tk 8.4 and 8.5 at present. # Implementation A full implementation, with documentation and tests is available at SourceForge <http://sf.net/tracker/?func=detail&aid=1247835&group_id=12997&atid=112997> . The bug report also contains some further discussion on this issue. # Copyright This document has been placed in the public domain. |
Name change from tip/257.tip to tip/257.md.
|
| < | < | | | | | | | | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | < | > | | | | < | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | < > | | | | | < > | | | | | | | | | | | | | | | | | | | | | | | < < | > > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | < > | | | < | > | | | | | | < > | | | < < | > > | | | | < > | | | < < | > > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 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 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 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 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 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 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 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 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 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 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 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 | # TIP 257: Object Orientation for Tcl Author: Donal K. Fellows <[email protected]> Author: Will Duquette <[email protected]> Author: Steve Landers <[email protected]> Author: Jeff Hobbs <[email protected]> Author: Kevin Kenny <[email protected]> Author: Miguel Sofer <[email protected]> Author: Richard Suchenwirth <[email protected]> Author: Larry W. Virden <[email protected]> State: Final Type: Project Vote: Done Created: 26-Sep-2005 Post-History: Obsoletes: 50 Tcl-Version: 8.6 ----- # Abstract This TIP proposes adding OO support to the Tcl core, semantically inspired by XOTcl. The commands it defines will be in the **::oo** namespace, which is not used by any current mainstream OO system, and it will be designed specifically to allow other object systems to be built on top. # Rationale and Basic Requirements Tcl has a long history of being comparatively agnostic about object-oriented programming, not favouring one OO system over another while promoting a wealth of OO extensions such as [incr Tcl]<http://incrtcl.sourceforge.net/itcl/> , OTcl<http://bmrc.berkeley.edu/research/cmt/cmtdoc/otcl/> , XOTcl<http://media.wu-wien.ac.at/> , stooop<http://jfontain.free.fr/stooop.html> , Snit<http://www.wjduquette.com/snit/> , etc. because in general, one size fits nobody. However, many application domains require OO systems and having a common such base system will help prevent application and library authors from reinventing the wheel each time through because they cannot rely on an OO framework being present with each and every Tcl installation. For example, the http package supplied with Tcl has its own internal object model, and a similar mechanism is reinvented multiple times within tcllib. Other parts of tcllib do their own thing \(to say nothing of the fact that both stooop and Snit are in tcllib themselves\). This does not promote efficient reuse of each others code, and ensures that each of these packages has a _poor_ object system. The request for an OO system is also one of the biggest feature requests for Tcl, and would make it far easier to implement megawidgets. It also leaves Tcl open to the ill-informed criticism that it doesn't support OO, despite being spoilt for choice in reality through the extensions listed above. Given all this, the time has come for the core to provide OO support. The aim of the core OO system shall be that it is simple to get started with, flexible so that it can take you a long way, fast \(we all know that we're going to get compared on this front!\), and suitable for use as a foundation of many other things, including the re-implementation of various existing OO extensions, including those that are currently compiled and also those that are pure Tcl extensions. Another requirement is that programmers should not have to alter all of their existing code in order to get started with the new system; rather, they should be able to adopt it progressively, over time, because it supports better ways of working \(e.g., faster and more flexible libraries\). # The Foundational OO System This TIP proposes that the foundation of the OO system should ensure that it is simple, fast and flexible. Semantically, the OO system should be using the semantic model pioneered by OTcl and XOTcl, as leveraging their experience on the complex parts \(e.g., the model of multiple inheritance, how to invoke superclass implementations of a method\) allows us to go straight to a solution that is rich enough for a very large space of applications. However, some changes relative to XOTcl are necessary. Certain aspects of XOTcl syntax are peculiar from a conventional OO point-of-view, and it is deeply unfortunate that a very large number of methods are predefined in the XOTcl base class. XOTcl's approach to object creation options is also highly idiosyncratic \(though critical to the way XOTcl itself works\) and doesn't really support the typical Tcl idioms. The changes must be made in such a way that something that works like classic XOTcl for virtually all uses can be built on the new framework, but the core object framework must also enable building [incr Tcl]-like or Snit-like object systems on top. Note that by keeping things in the base classes comparatively simple, it is much easier to build multiple extended OO frameworks on top. ## Key Features ### Functional Requirements * Class-based object system. This is what most programmers expect from OO, and it is very useful for many tasks. * Allows per-object customization and dynamic redefinition of classes. * Supports advanced OO features, such as: > meta-classes: These are subclasses of **class**, which permit more advanced customization of class behaviour. > filters: These are constraints \(implemented in Tcl code, naturally\) on whether a method may be called. > mixins: These allow functionality to be brought into an object from other objects if necessary, enabling better separation of concerns. * A system for implementing methods in custom ways, so that package authors that want significantly different ways of doing a method implementation may do so fairly simply. Note that this will require additional C code to perform; this API will not be exposed directly to the script level \(since it makes little sense there\). ### Non-Functional Requirements Note that these requirements would need to be imposed on any implementation of an object system in the Tcl core code anyway. * The speed of the object system is something on which it is easy to predict that Tcl will end up being compared to other languages. Hence, the core OO system _must_ permit efficient implementation. * The core OO system must be clear code that it is easy for the Tcl maintainers to keep in good order. The Engineering Manual [[247]](247.md) will be followed. ## Key Alterations Relative to XOTcl The core OO system can be considered to be a derivative of XOTcl, much as C can be considered to be a derivative of Algol. However, like the C/Algol relationship, there are many changes between the core OO system and XOTcl; the _implementations_ are not common. * Object and class names in the core extension to be all lower-case, in line with best common practice in general Tcl code. * Methods have to be capable of being non-exported, by which we mean that they are not \(simply\) callable from contexts outside the object. * The majority of the API for updating an object or class's definition is to be moved to a separate utility command, **oo::define**. * More "conventional" naming of operations is to be used. * Many of the more advanced features of XOTcl are not present, especially when it is possible to implement them on top of other features. This particularly applies to: > \* Filter- and mixin-guards > \* Invariants > \* Pre- and post-conditions Note that this TIP does _not_ propose to actually include any XOTcl \(or Itcl or Snit or ...\) compatibility packages in the core; it is about forming a foundation on which they can be built \(which happens to also be a comparatively lightweight OO system in itself\). Such compatibility packages can either remain separate code, or be the subject of future TIPs. # Detailed Rationale for Not Using XOTcl ## Features of XOTcl that are Retained Many key semantic features of XOTcl are adopted with little or no change. In particular, the following critical features of the core object system shall be semantically the same as in XOTcl as they represent the best-of-breed in advanced object systems at the moment. ### Multiple Inheritance We shall support multiple inheritance \(MI\) because this is very difficult to add after the fact. The main problem with MI in languages like C\+\+ was always confusion caused by the fact that methods were resolved using integer offsets into method tables. By contrast, single inheritance is far too restrictive. By supporting mixins and filters, it becomes possible to build not just conventional OO systems in the C\+\+ or Java mould, but also to make Self-like prototype systems \(which requires mixins and subclassing of the class of classes to work\) and Aspect-like systems \(which require filters for efficient implementation\). As these are less well-known terms than those of normal inheritance, we define them here: mixin: An auxiliary _class_ whose behaviour is "mixed into" the current object or class, adding the mixin's methods to the target's methods. Often used to support cross-cutting functionality or object roles. filter: A nominated _method_ that is permitted to control whether all calls to any other method of a class or object occur. This control is achieved by the nominated filter method being chained on the front of the sequence of methods in the "implementation list" for the actual target method. Often used to support transparent orthogonal functionality, such as access control or result caching. ### The Method Dispatch Algorithm The use of a complex class graph model as described above requires a sophisticated algorithm to linearize any particular call of a method into a sequence of method implementations that should be called. This is the method dispatch algorithm. The algorithm works by scanning the graph of the object and its associated classes in the order given below, collecting implementations as they are found in a list, with an implementation coming in the _last_ position in the list it can be; if it would be in twice because of an "inheritance diamond", it comes in the later location. 1. Filters defined on classes mixed into the object or its class \(or superclasses\), with filters from a particular class processed in the order that they are described by that class. 2. Filters defined on the object, in the order that they are described in the object's filter list. 3. Filters defined on the class of the object \(or its superclasses\), with filters from a particular class processed in the order that they are described by that class. 4. Methods declared by mixins added to the object, with mixins being processed in the order that they are described in the object's mixin list \(the set of methods declared by the mixin are determined by recursively applying this algorithm\). 5. Methods declared by mixins added to the object's class or superclasses, with mixins to a particular class being processed in the order that they are described in the class's mixin list. 6. Methods declared by the object itself. 7. Methods declared by the object's class itself. 8. Methods declared by the object's class's superclasses, with superclasses being processed in the order that they are described in the class's superclass list. Given the above ordering, for each method on an object there is an ordered list of implementations. We dispatch the method by executing the first implementation on the list, which can then hand off to subsequent methods in the list in order using the **next** command \(described below\). Another way to view the ordering is that there are several layers to the ordering scheme. Firstly, there is the basic ordering which is: object, class, superclasses to root \(with multiple inheritance being processed in the listed order, and classes appearing in the linearized tree as late as possible\). Then there is the second-order ordering, which adds mixins to the front of the basic ordering, where the order of the mixins is processed in basic ordering. Finally, there is the third-order ordering which adds filters to the front of the second-order ordering, with filter name sources being processed in second-order ordering and the method chain for a particular filter being processed in second-order ordering order. Note that a filter being invoked as a filter is different to a filter being invoked as a normal method. If a filter method is invoked directly, then it will actually be invoked twice, once as a filter and once as a conventional method. ## Essential Changes Relative to XOTcl Unfortunately, not all features of XOTcl are suitable for a core object system. In particular, many more syntactic features need to be altered. This section describes these, together with the rationale for each change; the rationales are marked with the word "**Therefore**", in bold. ### Exported vs. Non-exported Methods In XOTcl, every class and every object has an associated namespace. The namespace associated with a class _::myclass_ is _::xotcl::classes::myclass_; the namespace associated with object _::myobject_ is simply _::myobject_. XOTcl "instprocs" are simply procs defined in a class \(or superclass\) namespace; XOTcl per-object "procs" are simply procs defined in an object's namespace. _Every such proc becomes an object subcommand._ This is part of the reason why XOTcl objects have such cluttered interfaces. Every method which is of use to the object appears in the object's interface - and there's no way to prevent this. **Therefore**, in the new oo system "**proc**s" and "**instproc**s" can be exported or non-exported. Exported procs appear as object subcommands; non-exported procs do not, but remain available as subcommands of the **my** command. In this way, the object itself can still use them, but they need appear in the object's interface only if desired. Additionally, the standard introspection system will need to be extended to allow determining of which methods are exported and which are not. ### The oo::define Command In XOTcl, the commands to define per-class methods, filters, and so on are subcommands of the class object; the commands to define per-object methods, filters, and so on are subcommands of the individual object. This is a problem, as it confuses the implementation-time interface with the run-time interface. The design is logical, given XOTcl's extreme dynamism; any implementation-time activity, such as defining a method or adding a filter can indeed be done at run-time. But again, this makes it difficult to define clean run-time interfaces for reusable library code. The solution described in the previous section, of making some methods private by declaring them non-exported, does not give us a full solution; having the **instproc** subcommand available only from instance code isn't all that useful. **Therefore**, we add two new commands, **oo::define** and **oo::objdefine**, which are used to define methods, filters, and so on. They can be called in two ways, with each command having essentially the same fundamental syntax. The first calling model is as follows: > **oo::define** _class subcommand args..._ > **oo::objdefine** _object subcommand args..._ For example, the following XOTcl code defines a class with two methods: xotcl::Class myclass myclass instproc dothis {args} { # body } myclass instproc dothat {args} { # body } In the new oo core, the matching code would be this: oo::class create myclass oo::define myclass method dothis {args} { # body } oo::define myclass method dothat {args} { # body } The two definition commands will also have a second calling model, in which they get passed a single definition script whose commands are the subcommands supported by the command as described above: > **oo::define** _class script_ > **oo::objdefine** _object script_ Thus, the above code could also be written as follows: oo::class create myclass oo::define myclass { method dothis {args} { # body } method dothat {args} { # body } } Finally, the constructor for the **oo::class** class is extended so that such a script can be used during class creation: oo::class create myclass { method dothis {args} { # body } method dothat {args} { # body } } This allows a class to be defined cleanly and concisely, while guaranteeing that all class details can still be modified later on using **oo::define**. To enable the easy definition of details of the class object at class definition time, a special subcommand, "**self**", will be provided that is equivalent to using **oo::objdefine** on the class. Note that because of the requirement for a distinction between public and private interfaces, **oo::define** and **oo::objdefine** will need two subcommands XOTcl doesn't currently provide: **export** and **unexport**. **export** takes as arguments a list of method names; all named methods are exported and become visible in the object or class's interface. **unexport** does the opposite. Note that by default, all methods that start with a lower-case letter \(specifically, names matching the glob pattern "[a-z]\*"\) will be exported by default and all other methods will be unexported. ### Standard Metaclasses XOTcl defines two standard Metaclasses, _xotcl::Object_ and _xotcl::Class_. _xotcl::Object_ is the root of the class hierarchy; all XOTcl classes implicitly inherit from _xotcl::Object_. XOTcl classes are themselves objects, and are instances of _xotcl::Class_. _xotcl::Class_ can itself be subclassed to produce different families of classes with different standard behaviours. The new core object system will use the same basic mechanism, based on the metaclasses **oo::object** and **oo::class**. However, one of the problems with XOTcl is that XOTcl objects have too much standard behavior; the new core object system must provide a simpler foundation, with the XOTcl behavior optionally available. **Therefore**, we will extract the features of _xotcl::Object_ and _xotcl::Class_ that are critical into our classes and leave all other functionality up to any subclasses or metaclasses that are defined. Thus **oo::object** will be the root of the class hierarchy. However, instances of **oo::object** will have a minimal set of standard methods, so that clean interfaces can be built on top of it, as can be done with Snit types and instances. Core object system classes will be instances of **oo::class** or its subclasses. Likewise, **oo::class** will define only minimal behaviour. ### Inheritance A class may wish to make use of the capabilities of **oo::class** internally without exporting its methods \(e.g., for providing a singleton instance\). **Therefore**, the inheritance mechanism should be extended such that the newly defined class can declare whether a parent class's methods should be exported or not, on a case-by-case basis. ### Object Creation XOTcl has a unique creation syntax. The object name can be followed by what look like Tk or Snit options - but aren't. Instead, any token in the argument list that begins with a hyphen is assumed to be the name of one of the object's methods; it must be followed by the method's own arguments. For example, a standard XOTcl class will have a "set" method, which has the same syntax as the standard Tcl "set" command. Thus, the following code: myclass myobj -set a 1 -set b 2 creates an instance of "myclass" called "myobj" whose instance variables "a" and "b" and set to 1 and 2 respectively. This is an intriguing and innovative interface, and it is unlike any other Tcl object system. Additionally, it makes it difficult to implement standard Tk-like options. **Therefore**, standard core object system classes will not use this mechanism \(though it might be available on demand by inheriting from some other standard metaclass\). Instead, standard core object system classes will have no creation behavior other than that implemented by their designers in their constructors. Constructors may have any argument list the user pleases, including default arguments, the "args" argument \(as in the **proc** command\), and XOTcl-style non-positional arguments. It is up to the developer to handle the arguments appropriately. It is expected that one of the key responsibilities of any XOTcl compatability package would be to define an object/class construction system that parses the arguments in the expected way and uses them to invoke methods on the newly created object. ### Constructor Syntax In XOTcl, a class's constructor is implemented using its "init" instproc. This is troubling; constructors are intended to do things just once, and are often written to take advantage of that, whereas an "init" instproc can theoretically be called at any time. For any given class, then, one of two conditions will obtain: either "init" must be written so that it can be called at any time, or the class will have an inherent logic bug. **Therefore**, the class constructor will not be implemented as a standard instproc. Instead, the **oo::define** command will have a new subcommand, **constructor**, which will be used as follows: oo::define myclass constructor {} { # body } The constructor so defined will act almost exactly like an instproc; it may call superclass constructors using the "super" command, etc. However, it may never be called explicitly, but only via the class's "create" and "new" methods. ### Destructor Syntax In XOTcl, a class's destructor is defined by overriding the "destroy" instproc. This is problematic for two reasons: first, a destructor doesn't need an argument list. An instproc is too powerful for the task. Second, successful destruction should not depend on the destructor's chaining to its superclass destructors properly. **Therefore**, the class destructor will be defined by a new subcommand of **oo::define**, **destructor**, as follows: oo::define myclass destructor { # Body } The destructor has no argument list. The destructor cannot be called explicitly. Instead, the destructors are invoked in the proper order by the standard **destroy** method \(defined in **oo::object**\), which need never be overridden. If an error occurs in a destructor, it will _not_ prevent the object from being deleted. There is no guarantee to run destructors when an interpreter or Tcl-enabled process exits. ### Behavior and Syntax of next In XOTcl, the **next** command is used to invoke the "next" method in the dispatch chain. It optionally takes arguments to process \(if they are omitted, it passes all arguments that were passed to the current method\) and it calls the appropriate superclass implementation. But it does so without adjusting the Tcl stack, which forces classes to take extreme care when implementing code that needs to access variables or evaluate scripts in the scope of the code that invoked the method in the first place. **Therefore**, the **next** command will perform Tcl stack management so that using **uplevel** and **upvar** in a method will be just like doing so in a normal procedure, no matter how the class containing that method is subclassed. In addition, the adoption of [[157]](157.md) makes explicit handling of arguments practical as code does not need to perform potentially troublesome operations with **eval**, and so **next** will always require that all argument be passed explicitly. This also makes it easier to decide to pass no arguments to a superclass implementation. ## Desirable Changes The changes described in this section are not absolutely essential to meeting the goals described earlier. However, they are desirable in that they lead to cleaner, more maintainable code. ### Class vs. Object Method Naming XOTcl has many features which can be applied to a class for use by all class instances, or to a single object. For example, a "filter" can be defined for a single object, while an "instfilter" can be defined for a class and applied to all instances of that class. This is exactly backward. Most behavior will be defined for classes; additional per-object behavior is the special case, and consequently should have the less convenient name. **Therefore**, all definition subcommands that begin with "inst" will be defined, in the core OO system without their "inst" prefix; the per-object subcommands will be manipulated via **oo::objdefine** or through the "self" prefix command \(described above\), to indicate that it is operating on the object itself and not the members of the class. Thus, a filter is defined on a class for its instances using the "filter" subcommand; a filter is defined on a particular object using the "self filter" subcommand \(actually a subcommand of a subcommand\). oo::define someCls { method foo {} {...} self { method bar {args} {...} filter bar } } ### Procs vs. Methods The word "proc" conveys a standalone function; an object's subcommands are more typically described as its "methods". **Therefore**, the core OO system will use "method" in place of "proc" for definitions. ### Public Names In XOTcl, the main objects are _xotcl::Class_ and _xotcl::Object_. However, the Tcl Style Guide dictates that public command names begin with a lower-case letter. **Therefore**, all public names in the _oo::_ namespace \(i.e. the standard classes\) will begin with a lower case letter, e.g., the standard core object system equivalents of _xotcl::Class_ and _xotcl::Object_ will be **oo::class** and **oo::object**. This does not constrain any code making use of the OO system from naming objects however it wants. # API Specification This section documents the core object system API in detail, based on the essential and desirable changes discussed in the previous sections. ## Helper Commands The namespace\(s\) that define the following three commands are not defined in this specification unless otherwise stated; all that is defined is that they will be on the object's **namespace path** during the execution of any method and should always be used without qualification. ### my The **my** command allows methods of the current object to be called during the execution of a method, just as if they were invoked using the object's command. Unlike the object's command, the **my** command may also invoke non-exported methods. > **my** _methodName_ ?_arg_ _arg_ ...? Note that each object has its own **my** command; they are all distinct from each other. This means that it is suitable for use for things like invoking callbacks \(from general Tcl code\) that are non-public methods. In particular, the use of **namespace code** for encapsulating the use of **my** for invoking unexported callback methods by non-object code is supported. Note that the **my** command does not represent the name of the object. ### next The **next** command allows methods to invoke the implementation of the method with the same name in their superclass \(as determined by the normal inheritance rules; if a per-object method overrides a method defined by the object's class, then the **next** command inside the object's method implementation will invoke the class's implementation of the method\). The arguments to the **next** command are the arguments to be passed to the superclass method. The current stack level is temporarily bypassed for the duration of the processing of the **next** command; this allows a method to always execute identically with respect to the main calling context without needing to use some form of introspection to determine where that context is on the call frame stack \(with a side effect of isolating method implementations from each other\). > **next** ?_arg_ _arg_ ...? It is an error to invoke the **next** command when there is no superclass definition of the current method. ### self The **self** command allows executing methods to discover information about the object which they are currently executing in; it's always an error if not inside a method. Without arguments, the **self** command returns the current fully-qualified name of the object \(to promote backward compatability\). Otherwise, it is a command in the form of an ensemble \(though it is not defined whether it is manipulable with **namespace ensemble**\). The following subcommands of **self** are defined. None of these subcommands take additional arguments. caller: Returns a three-item list describing the class, object and method that invoked the current method, respectively. The syntax is as follows: > **self caller** class: Returns the name of the class that defines the currently executing method. If the method was declared in the object instead of in the class, this returns the class of the object containing the method definition. The syntax is as follows: > **self class** filter: When invoked inside a filter, returns a three-item list describing the object or class for which the filter has been registered. The first element is the name of the class or object, the second element is either **class** \(for a filter defined on a class for its instances\) or **object** \(for a filter defined on a single object\), and the third element is the name of the method. The syntax is as follows: > **self filter** method: Returns the name of the currently executing method. The syntax is as follows: > **self method** namespace: Returns the namespace associated with the current object. The syntax is as follows: > **self namespace** next: Returns a two-element list describing the method that will be executed when the **next** command is invoked, or an empty list if there is no subsequent definition for the method. The first element of the list is the name of the object or class that contains the method, and the second element of the list is the name of the method. The syntax is as follows: > **self next** object: Returns the name of the current object, the same as if the **self** command is invoked with no arguments. The syntax is as follows: > **self object** target: When invoked from a filter, returns a two-item list consisting of the name of the class that holds the target method and the name of the target method. The syntax is as follows: > **self target** For all these commands, when the name of a method is returned, it will be "_<constructor>_" when the method is a constructor, and "_<destructor>_" when the method is a destructor. It should be noted that these are not the actual names of the constructor and destructor \(they are unnamed methods\); they are just notational conventions supported by the **self** command. ## The oo::define Command > **oo::define** _class_ _subcommand_ ?_arg_ ...? > **oo::define** _class_ _script_ > **oo::objdefine** _object_ _subcommand_ ?_arg_ ...? > **oo::objdefine** _object_ _script_ The **oo::define** command is used to add behavior to classes, and the **oo::objdefine** command is used to add behavior to objects. The first form of each command is conventional for ensemble-like commands, except that the _class_ or _object_ argument precedes the _subcommand_ argument. In the second form of each command, _script_ is a Tcl script whose commands are the subcommands of **oo::define** or **oo::objdefine**; this is a notational convenience, as the two forms are semantically equivalent in what their capabilities are. \(Note that the context in which _script_ executes is otherwise not defined.\) ### Class-related Subcommands The subcommands of **oo::define** \(which may be unambiguously abbreviated in both the subcommand form and the script form\) shall be: * **constructor** - this takes two arguments \(a **proc**-style argument list, and a body script\), and sets the constructor for the instances of the class to be executed as defined by the body script after binding the actual arguments to the call that creates an instance of the class to the formal arguments listed. The constructor is called after the object is created but before any instance variables are guaranteed to be set. If no constructor is specified, the constructor will accept exactly the same arguments as the constructor in the parent class, and will delegate all the arguments to that parent-class constructor. The syntax is as follows: > **oo::define** _class_ **constructor** _argList_ _body_ > Note that constructors of class mixins are also called, but constructors of object mixins are never called \(as the object must exist before it can have an auxiliary class mixed into it\). * **destructor** - this defines the class destructor; a destructor is like a method but takes no arguments. Destructors are called on all classes that define them when the object is deleted, including classes that have been mixed in. The syntax is as follows: > **oo::define** _class_ **destructor** _body_ > Note that destructors _should always_ use the **next** command within their implementation so that destructors of parent classes are also executed. > Note also that destructors are called whenever the object is deleted by any mechanism \(except when the overall interpreter is deleted, when execution of Tcl scripts has ceased to be possible anyway\). * **export** - this specifies that the named methods are exported, i.e., part of the public API of the class's instances. The syntax is as follows: > **oo::define** _class_ **export** _name_ ?_name_ ...? > An exported method is accessible to clients of the class's instances; an unexported method is accessible only to the instances' own code through the **my** command. * **filter** - this subcommand controls the list of filter methods for a class. Each filter method in the list is called when any method is invoked on the class's instances, and it is up to the filter to decide whether to invoke the filtered method call \(using the **next** command\) or return a suitable replacement value. The syntax is as follows: > **oo::define** _class_ **filter** ?_filterName filterName_ ...? * **forward** - this subcommand defines a class method which is automatically forwarded \(i.e. delegated\) to some other command, according to a simple pattern. Each _arg_ is used literally. The syntax is as follows: > **oo::define** _class_ **forward** _name_ _targetCmd_ ?_arg_ ...? * **method** - this subcommand \(only valid for classes\) defines a class method \(i.e. a method supported by every instance of the class\). By default, methods are exported if they start with a lower-case letter \(i.e., any character in \\u0061 to \\u007a inclusive\) and are not exported otherwise. The syntax is as follows: > **oo::define** _class_ **method** _name_ _args_ _body_ * **mixin** - This subcommand defines a mixin for a class which is a way of bringing in additional method implementations \(which may add to or wrap existing methods\) on an _ad hoc_ basis. The list of mixins is traversed when searching for methods before the inheritance hierarchy, and mixed-in methods may chain to any methods they override using the **next** command. The syntax is as follows: > **oo::define** _class_ **mixin** ?_mixinClass mixinClass_ ...? * **self** - This subcommand, which has the same syntax patterns as **oo::objdefine**, allows the manipulation of the class as an object. See **oo::objdefine** below for a description of the list of subcommands of **self**. The syntaxes are as follows: > **oo::define** _class_ **self** _subcommand_ ?_arg_ ...? > **oo::define** _class_ **self** _script_ * **superclass** - This specifies the superclass \(or classes\) of a class. Note that objects are always either classes or not classes, and cannot be changed from one to the other by any mechanism. The syntax is as follows: > **oo::define** _class_ **superclass** _classList_ * **unexport** - This specifies that the named methods are unexported, i.e., private. The syntax is as follows: > **oo::define** _class_ **unexport** _name_ ?_name_ ...? > An exported method is accessible to clients of the object; an unexported method is accessible only to the object's own code, through the **my** command. The following utility subcommands are also supported: * **deletemethod** - This deletes one or more methods from a class; it doesn't modify any definitions of the method in superclasses, subclassses, instances or mixins. The method names must be specified exactly. Syntax is as follows: > **oo::define** _class_ **deletemethod** _name_ ?_name_ ...? * **renamemethod** - This renames a method in a class from one thing to another; it doesn't modify any definitions of the method in superclasses, subclassses, instances or mixins. Syntax is as follows: > **oo::define** _class_ **renamemethod** _fromName_ _toName_ ### Per-Object Subcommands The following subcommands are all per-object versions of the class subcommands listed above. When they are applied to a class, they operate on the class instance itself as an object, and not on the instances \(current and future\) of that class \(which is why the distinction is required\). * **class** - This subcommand gets and sets the class of an object. Changing the class of an object can result in many methods getting added or removed. Objects may not be changed between being class-objects and and non-class objects. The syntax is as follows: > **oo::objdefine** _object_ **class** _className_ > Note that when the class is changed of an object, no methods are called on that object, or on either the source or target classes, to indicate that the change has been carried out. This is up to the caller of the **class** subcommand. * **deletemethod** - This is a per-object version of the **deletemethod** subcommand of **oo::define**, to which it is syntactically identical. * **export** - This is a per-object version of the **export** subcommand of **oo::define**, to which it is syntactically identical. * **filter** - This is a per-object version of the **filter** subcommand of **oo::define**, to which it is syntactically identical. * **forward** - This is a per-object version of the **forward** subcommand of **oo::define**, to which it is syntactically identical. * **method** - This is a per-object version of the **method** subcommand of **oo::define**, to which it is syntactically identical. * **mixin** - This is a per-object version of the **mixin** subcommand of **oo::define**, to which it is syntactically identical. * **renamemethod** - This is a per-object version of the **renamemethod** subcommand of **oo::define**, to which it is syntactically identical. * **unexport** - This is a per-object version of the **unexport** subcommand of **oo::define**, to which it is syntactically identical. ## The oo::copy Command The **oo::copy** command creates an exact copy of an object with the given name. If _newName_ is the empty string or unspecified, a new name will be generated automatically. The syntax is as follows: > **oo::copy** _object_ ?_newName_? Note that this command does _not_ copy the backing namespace, and nor does it execute any constructors. It is therefore up to the caller to copy such internal state of the object in the manner suitable for the object and its class tree; it is suggested that this be done by wrapping the **oo::copy** command in another command that defines which method is called. # Core Objects The following classes are defined, and are the only pre-constructed objects in the core system. ## oo::object The root of the class hierarchy is **oo::object**. There are two ways to create a new instance of an object. > **oo::object** **create** _name_ > **set** _var_ **[** **oo::object** **new** **]** The first constructs a new object called _name_ of class _oo::object_; the object is represented as a command in the current scope. The second constructs a new object of class **oo::object** with a name guaranteed to be different from every existing command and returns the fully qualified of the command created \(which it is naturally a good idea to save in a variable, perhaps called _var_\). The name of an object is also the name of a command in the form of an ensemble where the subcommands of the ensemble are the _exported_ method names of the object. The command is not manipulable with **namespace ensemble**, but may be renamed. The new object has one predefined exported method \(**destroy**\) and four predefined non-exported methods \(**eval**, **unknown**, **variable** and **varname**\). Other subcommands and other behaviour can be added using **oo::define**. The **oo::object** class \(an instance of **oo::class**\) serves as the base class for all other core OO system classes. ### Constructor and Destructor The constructor for the **oo::object** class takes no arguments and does nothing. \(The actual construction of an object is special and happens before any constructors are called.\) The destructor does nothing. \(The actual destruction of an object is special and happens after all destructors have completed.\) ### Methods The instances of **oo::object** \(i.e. all objects and classes\) have the following methods: eval: This non-exported method concatenates its arguments according to the rules of **concat**, and evaluates the resulting script in the namespace associated with the object. The result of the script evaluation is the result of the _object_ **eval** method. The syntax is as follows: > _object_ **eval** ?_arg_ _arg_ ...? destroy: This exported method deletes the object; it takes no additional arguments and returns the empty string as its result. The syntax is as follows: > _object_ **destroy** unknown: This non-exported method takes a method name and an arbitrary number of extra arguments and handles the absence of a method with the given name. The default implementation just generates a suitable error message that explains what commands are available given how the caller attempted to invoke the method, and ignores all the additional arguments. The syntax is as follows: > _object_ **unknown** _methodName_ ?_arg_ ...? > Note that this method is not normally invoked directly. variable: This non-exported method takes an arbitrary number of _unqualified_ variable names and binds the variable with that name in the object's namespace to the same name in the current scope, provided the current scope is the body of a procedure, procedure-like method, or lambda term \(as used with **apply**\); if executed in a context where the current scope does not admit local variables, this method will have no effect. The syntax is as follows: > _object_ **variable** ?_varName_ _varName_ ...? > However, it will be more commonly used as: > **my variable** ?_varName_ _varName_ ...? > Each _varName_ argument is the name of a variable in the namespace associated with the object, and must not contain any namespace separators. Each named variable will be bound to a local variable in the current scope with the same name. varname: This non-exported method takes one argument, the name of a variable to be resolved in the context of the object's namespace, and returns the fully qualified name of the variable such that it can be used with the **vwait** command or extensions such as Tk \(e.g., for the **label** widget's **-textvariable** option\). This method does not assign any value to the variable. The syntax is as follows: > _object_ **varname** _varName_ > However, it will be more commonly used as: > **my varname** _varName_ ### Unknown Method Handling When an attempt is made to invoke an unknown method on any object, the core then attempts to pass _all_ the arguments \(including the method name\) to the **unknown** method of the object. The default implementation of the **unknown** method is specified by the **oo::object** class, and just generates a suitable "unknown subcommand" error message. ## oo::class This class is the class of all classes \(i.e. its instances are objects that manufacture objects according to a standard pattern\). Note that **oo::object** is an instance of **oo::class**, as is **oo::class** itself. > **oo::class** **create** _name_ ?_definition_? This creates a new class called _name_; the class is an object in its own right \(of class **oo::class**\), and hence is represented as a command in the current scope. **oo::class** returns the fully qualified command name. The newly-created class command is used to define objects which belong to the class, just as **oo::object** is. By default, instances of the new class have no more behaviour than instances of **oo::object** do; new class behavior can be added to the class in two ways. First, a _definition_ can be specified when creating the class; second, additional behaviour can be added to the class using **oo::define**. The definition, if given, consists of a series of statements that map to the subcommands of **oo::define**. The following three code snippets are equivalent; each defines a class called **::dog** whose instances will have two subcommands: **bark** and **chase**. # Method 1 oo::class create dog oo::define dog method bark {} { puts "Woof, woof!" } oo::define dog method chase {thing} { puts "Chase $thing!" } # Method 2 oo::class create dog oo::define dog { method bark {} { puts "Woof, woof!" } method chase {thing} { puts "Chase $thing!" } } # Method 3 oo::class create dog { method bark {} { puts "Woof, woof!" } method chase {thing} { puts "Chase $thing!" } } ### Constructor and Destructor The constructor for **oo::class** concatenates its arguments and passes the resulting script to **oo::define** \(along with the fully-qualified name of the created class, of course\). Classes have no destructor by default. \(Actual class destruction is special, and happens after all destructors have been executed.\) ### Methods The instances of **oo::class** have the following methods: create: Creates a new instance of the class with the given name. All subsequent arguments are given to the class's constructor \(and so must actually match the syntax pattern specified in the constructor definition\). The result of the **create** method is always the fully-qualified name of the newly-created object. The syntax is as follows: > _class_ **create** _objName_ ?_arg_ _arg_ ...? new: Creates a new instance of the class with an automatically chosen name. All subsequent arguments are given to the class's constructor \(and so must actually match the syntax pattern specified in the constructor definition\). The result of the **new** method is always the fully-qualified name of the newly-created object. The syntax is as follows: > _class_ **new** ?_arg_ _arg_ ...? > Note that the _oo::class_ object itself does not export the **new** method; it is good practice for all classes to have names. createWithNamespace: Creates a new instance of a class with a given name and a given name of backing namespace. This method \(required to provide proper support for putting [incr Tcl] on top of the core OO system\) is not exported by default. Apart from the _nsName_ parameter, it is the same as the **create** method. > _class_ **createWithNamespace** _objName nsName_ ?_arg arg_ ...? # Introspection Support The core Tcl **info** command shall be extended in the following ways. ## An [info object] Subcommand An **object** subcommand that shall provide information about a particular object. Its first argument shall be the name of an object to get information about, its second argument shall be a subsubcommand indicating the type of information to retrieve and all subsequent arguments shall be arguments, as appropriate. The following types of information shall be available: class: Returns the class of an object, or if _className_ is specified, whether the object is \(directly or indirectly through inheritance or mixin\) an instance of the named class. > **info object class** _object_ ?_className_? definition: Returns the formal argument list and body used to define a method. > **info object definition** _object method_ filters: Returns the list of filters defined for an object. > **info object filters** _object_ forward: Returns the list of words that form the command prefix that a method is forwarded to. > **info object forward** _object method_ isa: Returns boolean information about how an object relates to the class hierarchy. Supports a range of subcommands to allow the specification of what sort of test is to be performed: > class: Returns whether the named object is a class. > > **info object isa class** _object_ > metaclass: Returns whether the named object is a class that can create other classes \(i.e. is **oo::class** or one of its subclasses\). > > **info object isa metaclass** _object_ > mixin: Returns whether the named object has _mixinClassName_ as one of its mixins. > > **info object isa mixin** _object mixinClassName_ > object: Returns whether _object_ really names an object. > > **info object isa object** _object_ > typeof: Returns whether the object is of type _class_ \(i.e. an instance of that class or an instance of a subclass of that class\). > > **info object isa typeof** _object class_ methods: Returns the list of methods defined for an object. Supports the options **-all** to also look at the class hierarchy for the object, and **-private** to get the list of methods supported by **my** for the object. > **info object methods** _object options_ mixins: Returns the list of mixins for an object. > **info object mixins** _object_ vars: Returns the list of all variables defined within the object, or optionally just those that match _pattern_ according to the rules of **string match**. > **info object vars** _object_ ?_pattern_? ## An [info class] Subcommand A **class** subcommand that shall provide information about a particular class. Its first argument shall be the name of a class to get information about, its second argument shall be a subsubcommand indicating the type of information to retrieve and all subsequent arguments shall be arguments, as appropriate. The following types of information shall be available: constructor: Returns the formal argument list and body used to define the constructor, or an empty list if no constructor is present. > **info class constructor** _class_ definition: Returns the formal argument list and body used to define a method. > **info class definition** _class method_ destructor: Returns the body of the destructor, or an empty string if no destructor is present. > **info class destructor** _class_ filters: Returns the list of filters defined for a class. > **info class filters** _class_ forward: Returns the list of words that form the command prefix that a method is forwarded to. > **info class forward** _class method_ instances: Returns a list of all direct instances of the class \(but not instances of any subclasses of the class\), or optionally just those that match _pattern_ according to the rules of **string match**. > **info class instances** _class_ ?_pattern_? methods: Returns the list of methods defined by a class. Supports the options **-all** to also look at the class hierarchy, and **-private** to get the list of methods supported by **my** for the object's instances. > **info class methods** _class options_ subclasses: Returns a list of all subclasses of the class, or optionally just those that match _pattern_ according to the rules of **string match**. > **info class subclasses** _class_ ?_pattern_? superclasses: Returns a list of all superclasses of the named class in the class hierarchy. The list will be ordered in inheritance-precedence order. > **info class superclasses** _class_ ## Extending the Introspection Capabilities Other forms of introspection subcommands may be added to **info object** and **info class** by creating exported commands in the namespaces **oo::InfoObject** and **oo::InfoClass** respectively. ## Issues with Objects and Namespaces Every object has a distinct namespace associated with it, the name of which is outside the scope of this specification. It is the name of this namespace that is returned by **self namespace**. The namespace does have a path set, as if by calling **namespace path**; this is how the **next** and **self** commands are provided, though since they are never usable outside the scope of the body of a method, the namespace which they originate from is out of the scope of this specification. The **my** command is the only command in the object's namespace by default \(i.e., this command is truly per-object\). It is not exported from the object's namespace, nor are any other commands exported from or imported into the namespace. Methods are not commands, and so completely ignore the **namespace export** command, nor does **namespace unknown** get involved at any point during the location of a method. \(They may run during the processing of a method body; it is a context very similar to a normal procedure body.\) Similarly, a method may not be **namespace import**ed from another namespace. Each method \(including both the constructor and destructor\) executed by an object executes in that object's namespace. Changes made by a method to the namespace \(including both command declaration and uses of **namespace import**\) will be seen by all other methods invoked on the same object. Note that methods declared by classes still execute in the instance objects' namespaces. # C API _Note: This API is probably incomplete. Future TIPs may extend or completely revise it._ ## Datatypes The following public datatypes shall be declared in tcl.h: Tcl\_Object: An opaque handle to an object. Tcl\_Class: An opaque handle to a class. Tcl\_Method: An opaque handle to a method. Tcl\_ObjectContext: An opaque handle to an object method call context. Tcl\_MethodType: A structure describing the type of a method implementation. It shall have the following fields: > version: The version number of the structure, which should always be referred to as TCL\_OO\_METHOD\_VERSION\_CURRENT in source code \(currently ignored, but allows transparent versioning in the future\). > name: The name of the method type, for debugging. > callProc: A pointer to a function that defines how to call method implementations of this type. Must not be NULL. > deleteProc: A pointer to a function that defines how to delete the _clientData_ associated with a particular method implementation instance. If NULL, no deletion of the _clientData_ is required. > cloneProc: A pointer to a function that defines how to copy the _clientData_ associated with a particular method implementation instance during the copying of an object or class with **oo::copy**. If NULL, the method will be cloned by just copying the _clientData_. Tcl\_ObjectMetadataType: A structure describing the type of some arbitrary non-NULL metadata attached to an object or class. It shall have the following fields: > version: The version number of the structure, which should always be referred to as TCL\_OO\_METADATA\_VERSION\_CURRENT in source code \(currently ignored, but allows for transparent versioning in the future\). > name: The name of the metadata type, for debugging. > deleteProc: A pointer to a function that defines how to delete some metadata associated with this type. Must not be NULL. > cloneProc: A pointer to a function that defines how to copy some metadata associated with this type during the copying of an object or class with **oo::copy**. If NULL, the metadata will not be copied. \(_Open issue:_ There is a use case for making objects unclonable; consider the case where the metadata consists of one or more OS resource handles. Simply shallow-copying resource handles is a bad idea, but deep-copying them may well be infeasible. Not all objects can handle copy-on-write semantics gracefully.\) Tcl\_MethodCallProc: The type of the _callProc_ field of the Tcl\_MethodType structure. It is a pointer to a function that is used to implement how a method implementation is called. It takes five arguments and returns a normal Tcl result code. The arguments are: > clientData: Some method implementation instance specific data. Note that this is specific to the instance of the method implementation, and not \(necessarily\) the instance of the object. > interp: The Tcl interpreter reference. > objectContext: The object method call context, through which useful information \(such as what object this method was invoked upon\) can be obtained. > objc: The number of arguments. > objv: The actual list of arguments. Since the number of arguments required to indicate the method may vary, the method implementation should look up how many to skip over using the object method call context. Tcl\_MethodDeleteProc: The type of the _deleteProc_ field of the Tcl\_MethodType structure. It is a pointer to a function that is used to delete _clientData_ values associated with a method instance. It takes a single argument \(the _clientData_ to delete\) and has no return value. Tcl\_MethodCloneProc: The type of the _cloneProc_ field of the Tcl\_MethodType structure. It is a pointer to a function that is used to make copies of _clientData_ values associated with a method instance suitable for use in another method instance. It takes two arguments \(the _clientData_ to clone, and a pointer to a variable into which to write the cloned _clientData_\) and returns either TCL\_OK or TCL\_ERROR, with the method only being cloned if the result is TCL\_OK \(the method is silently not cloned otherwise\). Tcl\_ObjectMapMethodNameProc: The type of a callback function used to adjust the mapping of objects and method names to implementations, which is required to support building [incr Tcl] on top of the core OO system. It takes four arguments, being the interpreter, the object that the method is being invoked upon, a point to a variable to contain the class in the hierarchy to start the search for components of the method chain from, and an unshared object holding the method name as supplied and which can be modified if the method to look for is not the literal name passed in. > This is necessary because [incr Tcl] allows the invoking of superclass implementations of a method using a syntax like "_superclassName_::_methodName_" where _superclassName_ may name any superclass of the current class, and _methodName_ may be any method name. > Note that the exact definition of this type is subject to change at the moment in order to ensure that it can be connected to the method dispatch engine efficiently. The type will be finalized before the release of Tcl 8.6. Tcl\_ObjectMetadataDeleteProc: The type of the _deleteProc_ field of the Tcl\_ObjectMetadataType structure. It is a pointer to a function that is used to delete _metadata_ values attached to an object or a class. It takes a single argument \(the _metadata_ to delete\) and has no return value. Tcl\_ObjectMetadataCloneProc: The type of the _cloneProc_ field of the Tcl\_ObjectMetadataType structure. It is a pointer to a function that is used to create a copy of _metadata_ values attached to an object or a class. It takes three argument, \(the interpreter, the _metadata_ to copy, and a pointer to a variable into which to write the copy, or NULL if the copy is not to be performed\) and returns a standard Tcl result code. ## Functions The following functional operations are defined: Tcl\_NewMethod: This function creates a new method on a class \(and hence on all instances of that class\). It has the following signature: > Tcl\_Method **Tcl\_NewMethod**\(Tcl\_Interp \*_interp_, Tcl\_Class _cls_, Tcl\_Obj \*_nameObj_, int _isPublic_, const Tcl\_MethodType *_typePtr_, ClientData _clientData_\) > If the method is created with a NULL _nameObj_, it must be installed manually into the class as a constructor or destructor \(in the latter case, it is important that the method be able to execute without additional arguments\). Note that a NULL _typePtr_ is reserved for internal use. Tcl\_ClassSetConstructor: This function installs a method into a class as a constructor for instances of that class. The method must have been created with **Tcl\_NewMethod** with a NULL _nameObj_ argument. It has the following signature: > void **Tcl\_ClassSetConstructor**\(Tcl\_Class _cls_, Tcl\_Method _method_\) Tcl\_ClassSetDestructor: This function installs a method into a class as a destructor for instances of that class. The method must have been created with **Tcl\_NewMethod** with a NULL _nameObj_ argument. It has the following signature: > void **Tcl\_ClassSetConstructor**\(Tcl\_Class _cls_, Tcl\_Method _method_\) Tcl\_NewInstanceMethod: This function creates a new method on an object. It has the following signature: > Tcl\_Method **Tcl\_NewInstanceMethod**\(Tcl\_Interp \*_interp_, Tcl\_Object _object_, Tcl\_Obj \*_nameObj_, int _isPublic_, const Tcl\_MethodType *_typePtr_, ClientData _clientData_\) > Note that a NULL _typePtr_ is reserved for internal use, and _nameObj_ must not be NULL. Tcl\_NewObjectInstance: This function creates a new instance of a class, calling any defined constructors. It has the following signature, returning NULL \(and setting a message in the interpreter\) if the object creation failed: > Tcl\_Object **Tcl\_NewObjectInstance**\(Tcl\_Interp \*_interp_, Tcl\_Class _cls_, const char \*_name_, const char \*_nsName_, int _objc_, Tcl\_Obj \*const \*_objv_, int _skip_\) > Both _name_ and _nsName_ may be NULL, in which case the constructor code picks a default that doesn't clash with any previously existing commands or namespaces. Tcl\_CopyObjectInstance: This function creates a copy of an object \(including classes\) without copying the backing namespace or executing any constructors. It has the following signature, returning NULL \(and setting a message in the interpreter\) if the object copying failed: > Tcl\_Object **Tcl\_CopyObjectInstance**\(Tcl\_Interp \*_interp_, Tcl\_Object _sourceObject_, const char \*_targetName_\) > Note that the copying of an object can fail if the copy code for one of the metadata coping functions fails, so those functions can veto copying. Also note that if _targetName_ is NULL, a name will be picked for the object. Currently no control over the naming of the target object's namespace is provided. Tcl\_GetObjectFromObj: This function converts from a Tcl\_Obj holding the name of an object to a Tcl\_Object handle. It returns NULL \(leaving an error message in the interpreter\) if the conversion fails. > Tcl\_Object **Tcl\_GetObjectFromObj**\(Tcl\_Interp \*_interp_, Tcl\_Obj *_objPtr_\) Tcl\_ObjectContextInvokeNext: This function invokes the next method implementation in a method call chain, and is the internal implementation of the **next** command. It has the following signature: > int **Tcl\_ObjectContextInvokeNext**\(Tcl\_Interp \*_interp_, Tcl\_ObjectContext _context_, int _objc_, Tcl\_Obj \*const \*_objv_, int _skip_\) Tcl\_ClassGetMetadata: This function retrieves the metadata attached to the class _cls_ that is associated with the type _typePtr_. It returns NULL if no data of that type is attached. > ClientData **Tcl\_ClassGetMetadata**\(Tcl\_Class _cls_, const Tcl\_ObjectMetadataType \*_typePtr_\) Tcl\_ClassSetMetadata: This function attaches metadata, _metadata_, of a specific type, _typePtr_, to the class, _clazz_, or removes the metadata of that type if _metadata_ is NULL. It is a no-op to remove metadata of a type that is not attached in the first place. > void **Tcl\_ClassSetMetadata**\(Tcl\_Class _clazz_, const Tcl\_ObjectMetadataType \*_typePtr_, ClientData _metadata_\) Tcl\_ObjectGetMetadata: This function retrieves the metadata attached to the object _object_ that is associated with the type _typePtr_. It returns NULL if no data of that type is attached. > ClientData **Tcl\_ObjectGetMetadata**\(Tcl\_Object _object_, const Tcl\_ObjectMetadataType \*_typePtr_\) Tcl\_ObjectSetMetadata: This function attaches metadata, _metadata_, of a specific type, _typePtr_, to the object, _object_, or removes the metadata of that type if _metadata_ is NULL. It is a no-op to remove metadata of a type that is not attached in the first place. > void **Tcl\_ObjectSetMetadata**\(Tcl\_Object _object_, const Tcl\_ObjectMetadataType \*_typePtr_, ClientData _metadata_\) Tcl\_ObjectGetMethodNameMapper: This function retrieves the current method name mapping function for an object, or NULL if none was set. It has the following signature: > Tcl\_ObjectMapMethodNameProc **Tcl\_ObjectGetMethodNameMapper**\(Tcl\_Object _object_\) Tcl\_ObjectSetMethodNameMapper: This functionsets the method name mapping function for an object, or removes it if the function is set to NULL. It has the following signature: > void **Tcl\_ObjectSetMethodNameMapper**\(Tcl\_Object _object_, Tcl\_ObjectMapMethodNameProc _methodNameMapper_\) The following pure inspective \(i.e., non-state changing\) operations are defined: Tcl\_GetClassAsObject: This gets the object that represents a class. > Tcl\_Object **Tcl\_GetClassAsObject**\(Tcl\_Class _clazz_\) Tcl\_GetObjectAsClass: This gets the class that an object represents \(or NULL if the object does not represent a class\). > Tcl\_Class **Tcl\_GetObjectAsClass**\(Tcl\_Object _object_\) Tcl\_GetObjectCommand: This gets the command for an object. It is the name of this command that represents the object at the script level, and as such, it may be renamed. > Tcl\_Command **Tcl\_GetObjectCommand**\(Tcl\_Object _object_\) Tcl\_GetObjectNamespace: This gets the object's private namespace. > Tcl\_Namespace \***Tcl\_GetObjectNamespace**\(Tcl\_Object _object_\) Tcl\_MethodDeclarerClass: This gets the class that declared a method, or NULL if the method is a per-object method. > Tcl\_Class **Tcl\_MethodDeclarerClass**\(Tcl\_Method _method_\) Tcl\_MethodDeclarerObject: This gets the object that declared a method, or NULL if the method is a class method. > Tcl\_Object **Tcl\_MethodDeclarerObject**\(Tcl\_Method _method_\) Tcl\_MethodIsPublic: This returns whether a method is a public method. This status might be overridden in subclasses or objects. > int **Tcl\_MethodIsPublic**\(Tcl\_Method _method_\) Tcl\_MethodIsType: This returns whether a method is a specific type of method, and if so, also returns the _clientData_ for the type. No way of inspecting method types for which you do not have a pointer to the type structure is provided. > int **Tcl\_MethodIsType**\(Tcl\_Method _method_, const Tcl\_MethodType *_typePtr_, ClientData \*_clientDataPtr_\) Tcl\_MethodName: This returns the name of a method. > Tcl\_Obj \***Tcl\_MethodName**\(Tcl\_Method _method_\) Tcl\_ObjectDeleted: This returns whether an object has been deleted \(assuming deletion has not yet completed, i.e., that the destructor is currently being processed\). > int **Tcl\_ObjectDeleted**\(Tcl\_Object _object_\) Tcl\_ObjectContextIsFiltering: This returns whether the method call context is working with a filter or not. > int **Tcl\_ObjectContextIsFiltering**\(Tcl\_ObjectContext _context_\) Tcl\_ObjectContextMethod: This returns the method call context's current method instance. > Tcl\_Method **Tcl\_ObjectContextMethod**\(Tcl\_ObjectContext _context_\) Tcl\_ObjectContextObject: This returns the method call context's object \(i.e., the object which was invoked\). > Tcl\_Object **Tcl\_ObjectContextObject**\(Tcl\_ObjectContext _context_\) Tcl\_ObjectContextSkippedArgs: This returns the number of arguments to be skipped \(this varies because the method instance may be invoked through either [obj method ...] or through [next ...]\). > int **Tcl\_ObjectContextSkippedArgs**\(Tcl\_ObjectContext _context_\) # Not Addressed in this Document This TIP does not address the reqirements for management of variables on a class level or for "class methods" \(in the Java sense\). These will need to be the subject of future TIPs. # Copyright This document has been placed in the public domain. ---- The following sections are non-normative. # Appendix: Class Hierarchy for Support of Other OO Systems When using the OO system as a basis for some other object system, it is useful for all classes and objects to derive from some other object root for compatability with existing practice. To see how to do this, consider this class hierarchy \(targetted at XOTcl\) outlined below. The XOTcl _Object_ class would derive from the core **oo::object** class, and the XOTcl _Class_ class would derive from the core **oo::class** and the XOTcl _Object_ classes. This would give the following diagram \(core classes are in lower case with their namespace omitted, XOTcl classes are in upper case, with namespace omitted\). +--------+ ,------->| object | | +--------+ | ,^. creates | ______|______ | | | | +-------+ +--------+ `--| class | | Object |<-. +-------+ +--------+ | ,^. ,^. | |______ ______| | creates | | +-------+ | | Class |---------' +-------+ Note that **class** instances create **object**s \(or subclasses thereof\), but _Class_ instances create _Object_s \(or subclasses thereof\). # Appendix: XOTcl Features Omitted from the Core OO System ## Object Methods Object::autoname: This is trivially implemented in a small procedure, and core objects can pick names for themselves and are renameable. Object::check: Preconditions and postconditions are not supported \(they add a lot of complexity\) and neither are invariants. Hence, there is no need to control whether they are executed. Object::cleanup: This is not an especially well-defined method \(what if the object happens to hold handles to complex resources such as network sockets; it is not generally possible for the state of the remote server to be reset\) and can be added in any compatability layer. Object::configure: This feature has been deliberately omitted from the core object system. This would be value added by any XOTcl extension. Object::extractConfigureArg: This feature is part of **configure**. Object::getExitHandler: This feature is not necessary for this version. If it existed, it would not need to be a part of the base object. Object::info: The introspection features are moved into the core **info** command. Object::invar: Invariants may be implemented using filters. Object::move: This feature is equivalent to the use of the standard **rename** operation. Object::noinit: This feature has been deliberately omitted from the core object system because its use is dependent on the use of other deliberately-omitted features \(i.e., **configure**\). This would be value added by any XOTcl extension. Object::parameter and Object::parametercmd: The core object system provides tools for doing parameters, but does not provide an implementation on the grounds that it is pretty easy to add. Object::requireNamespace: Objects always have a namespace. Object::setExitHandler: See the comments for **getExitHandler** above. ## Class Methods Class::\_\_unknown: Auto-loading of unknown classes is handled by the standard core **unknown** mechanism. Class::abstract: Abstractness is relatively easy to implement on top of the proposed infrastructure and is not critical to getting an implementation. Class::allinstances: This feature is trivially implemented in a small procedure. Class::alloc: The core objects have no default behaviour, so the difference with the basic core class behaviour is moot. Class::create: Core object creation is a much more sealed process, but the lack of **configure**-like behaviour means that the complexity of this method is not necessary. Instead, constructors are called automatically. Class::parameterclass: Core object system parameters are not implemented by classes. Class::volatile: This feature is omitted as it is believed that it is possible to implement automated lifecycle management as a mixin. ## Other Commands getExitHandler, setExitHandler: Exit handlers are out of scope for the core object system. |
Name change from tip/258.tip to tip/258.md.
|
| < | < | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 258: Enhanced Interface for Encodings Author: Don Porter <[email protected]> State: Final Type: Project Vote: Done Created: 01-Oct-2005 Post-History: Keywords: encoding Tcl-Version: 8.5 ----- # Abstract This TIP proposes public C routines and a new **encoding dirs** subcommand to improve the interfaces to Tcl's encodings. # Background Several internal improvements have been made to the internals of how Tcl encodings are initialized, found, stored, and refcounted during Tcl 8.5 development. This TIP is primarily about making these improvements available via public interfaces. The lifetime of **Tcl\_Encoding** values has been identified as a problem \(Bug 1077262\), where premature freeing means repeated re-loading of encoding data. Since each encoding data load involves interaction with the filesystem, this can be an expensive mistake. The Tcl documentation has long claimed that by setting the value of a global variable **::tcl\_libPath** a script could influence the search path of directories where encoding data files are sought. That documentation has never been correct \(Bug 463190\). Tclkit suffers from an initialization dilemma. It stores encoding data files in a virtual filesystem. In particular the system encoding is often based on a data file in the virtual filesystem. The Tclkit virtual filesystem is \(largely\) script-implemented and cannot exist until a **Tcl\_Interp** has been created. However, Tcl wants to determine the correct value for the system encoding very early in its initialization, before any **Tcl\_Interp** gets created. The consequence is that Tclkit fails to successfully set the system encoding in Tcl's early initialization, and Tclkit has had to jump through hoops to get Tcl to repeat those early initialization steps after the virtual filesystem is in place. # Proposed changes Add the following routines to Tcl's public interface: > int **Tcl\_GetEncodingFromObj**\(Tcl\_Interp \*_interp_, Tcl\_Obj \*_objPtr_, Tcl\_Encoding \*_encodingPtr_\) Writes to \*_encodingPtr_ the **Tcl\_Encoding** value that corresponds to the value of _objPtr_, and returns **TCL\_OK**. The **Tcl\_Encoding** value is also cached as the internal rep of _objPtr_ so that the lifetime of the **Tcl\_Encoding** data in the process will be at least the lifetime of that internal rep of _objPtr_. The caller is expected to call **Tcl\_FreeEncoding** on *_encodingPtr_ when it no longer needs it. If no corresponding **Tcl\_Encoding** value for the value of _objPtr_ can be determined, **TCL\_ERROR** is returned, and an error message is stored in the result of _interp_. > Tcl\_Obj \***Tcl\_GetEncodingSearchPath**\(\) Returns a list of directory pathnames that Tcl's encoding subsystem will search for encoding data files when an encoding is requested that's not already loaded in the process. This will be the value stored by the last successful call to **Tcl\_SetEncodingSearchPath**. If no calls to **Tcl\_SetEncodingSearchPath** have occurred, Tcl will compute an initial value based on the environment. There is one encoding search path for the entire process, shared by all threads in the process. > int **Tcl\_SetEncodingSearchPath**\(Tcl\_Obj \*_searchPath_\) Stores _searchPath_ as the list of directory pathnames for Tcl's encoding subsystem to search for encoding data files, and returns **TCL\_OK**. Returns **TCL\_ERROR** only if _searchPath_ is not a valid Tcl list. There is no checking for validity of the directory pathnames, so for example, one can place a directory on the encoding search path before mounting the **Tcl\_Filesystem** that contains that directory. When searching for encoding data files, Tcl's encoding subsystem ignores any non-existent directories in the search path as well. > CONST char \***Tcl\_GetEncodingNameFromEnvironment**\(Tcl\_DString \*_bufPtr_\) This routine exposes Tcl's determination about what the system encoding should be, based on system calls and examination of the environment suitable for the platform. It accepts _bufPtr_, a pointer to an uninitialized or freed **Tcl\_DString** and writes to it the string value of the appropriate system encoding dictated by the environment. The **Tcl\_DStringValue** is returned. In a properly initialized Tcl, the string value returned by **Tcl\_GetEncodingNameFromEnvironment** ought to be the same as that returned by **Tcl\_GetEncodingName**\(**NULL**\); that is, the system encoding dictated by the environment ought to be the encoding Tcl will return as the result of **encoding system**. If these two results do not match, it indicates that at the time Tcl was initialized, the proper sytem encoding was not available. Perhaps the necessary data file was not on the encoding search path at that time. With this new routine, the check for this match can be performed, and if the match does not exist, a call to **Tcl\_SetSystemEncoding** can try again to get Tcl's system encoding to agree with what the environment dictates. Add a new subcommand, **encoding dirs** with syntax: > **encoding dirs** ?_searchPath_? This subcommand is the script-level interface to the **Tcl\_GetEncodingSearchPath** and **Tcl\_SetEncodingSearchPath** routines. When called without an argument, the current list of directory pathnames to be searched for encoding files is returned. When called with _searchPath_ argument, the value _searchPath_ is set as the new list of directory pathnames to be searched. The documentation for existing routines **Tcl\_GetDefaultEncodingDir** and **Tcl\_SetDefaultEncodingDir** will be updated to discourage their use and to encourage the use of **Tcl\_GetEncodingSearchPath** and **Tcl\_SetEncodingSearchPath** instead. # Compatibility This proposal includes only new features. It is believed that existing scripts and C code that operate without errors will continue to do so. The **encoding dirs** command has been available with the name **::tcl::unsupported::EncodingDirs** since the Tcl 8.5a3 release. It is proposed to remove this unsupported command completely, as it has only existed in alpha releases. Anyone using it should be able to migrate to **encoding dirs** without difficulty. # Reference Implementation The actual code is already complete as internals corresponding to the proposed public. Implementation is just an exercise in renaming, placing in stub tables, documentation, etc. # Copyright This document has been placed in the public domain. |
Name change from tip/259.tip to tip/259.md.
|
| < | < | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 259: Making 'exec' Optionally Binary Safe Author: Andreas Leitgeb <[email protected]> State: Draft Type: Project Vote: Pending Created: 12-Dec-2005 Post-History: Tcl-Version: 8.7 ----- # Abstract A new option shall be added to the command **exec**, that allows the user to specify that input redirected from immediate data \(using **<<**\) and/or the data received from the external command shall not undergo any translation within Tcl. # Motivation External programs may expect binary data, or write out binary data, or neither or even both. Whether a program reads/writes binary data or platform-encoded data is generally specific to the particular program and known by the programmer who intends to **exec** it from a Tcl script. For example, a hexdump-utility expectably reads binary data and outputs text. # Deficiencies of Current State of exec **Problem 1:** For passing string-data to external programs, **exec** now behaves arguably incorrect, because it does not pass through \\0-bytes. **Problem 2:** For returning the result of external programs, **exec** applies translations based on system-default encoding, which is OK in most cases, except, of course, for programs that output binary data. Problem 1 is actually a bug, but for compatibility reasons some internal function cannot be changed, because it is believed to be used by some extensions \(although it is not officially exported\), thus blocking the fixing of the bug. This TIP goes beyond that, by not having it fixed to some particular consistent behaviour, but to let the script-developer decide on what is the right behaviour for his needs. Problem 2 prevents the output of binary-outputting programs from being correctly retrieved. # Proposal for a New Option The **exec** command already has an interface for options, and currently supports one option **-keepnewline** and the end-of-options marker **--**. This means that adding a new option will not adversely affect any existing scripts. This TIP proposes a new option, **-binary** _arg_. _arg_ can be either a single boolean value: > if a boolean true then both input \(if a **<<** redirection is present\) and return value are passed verbatim between Tcl and the external program. > if a boolean false \(which is the default\) then behaviour would be like it is now, except for input being \\0-safe and system-translation taking place as appropriate \(e.g. line-endings\). _arg_ can also be one of the keywords **in**, **out**, **both** \(which is equivalent to 1\) or an empty string \(equivalent to 0\) for more readable code. The directions are to be seen from external programs perspective. If _arg_ is any true boolean value, **both** or **out**, then the option **-keepnewline** is implied. If some usage of **exec** does not use **<<** string-redirection, then the **in**-bit has no visible effect. For now, no binary flag is defined for stderr. This might be subject of a future TIP or left out due to lack of need. # Alternatives Benjamin Riefenstahl suggested to not make a binary \(in the sense of yes/no\) decision for each of input and output, but to directly specify the encodings to use \(of which "binary" would also be a valid one\). This has some subtle disadvantage for usage. As proposed, there is \*one\* option with one argument of effectively 4 different values. From each of these values it is evident, on which channels conversion takes place. To specify arbitrary encodings independently for two channels, there would need to be a list of encodings. For consistency with other commands, the "stdin"-encoding would have to be first, though it is used rarelier than output-encoding. So most times one would have to pass -encoding \{\{\} binary\} \(yuck!\) to specify encoding for output only. Unlike with general channels \(as used for open \|... or sockets\) the data going through exec is always "limited": before actually calling exec it exists completely in memory as argument to exec, and afterwards output is returned as one single returnvalue. Each of these chunks can be handled as binary for exec, and explicitly converted through "encoding convertto" \(for input\) or encoding convertfrom \(for output\). Encoding per system-default is achieved by not adding any -binary option to exec at all, which covers probably >95% of all usages, anyway. \(the remaining 5% being the ones for whom this TIP has been written\) # Implementation No implementation exists right now, although it is possible that this will change in near future. An implementation would have to change these functions: Those functions that are not modifyable due to them being used elsewhere, need to be replaced by an extended version, and the old function can be changed to call the new one with appropriate extra arguments, and eventually be phased out. Tcl\_ExecObjCmd: Handle the new option and set new bits for the flags argument of _Tcl\_OpenCommandChannel_ or add a new bitset argument. Tcl\_OpenCommandChannel: Deal with the new bits, or with new argument and pass them/it on. TclCreatePipeline: needs new arguments _flags_ \(for solving bug \#768678 along the way\) and pass new arguments to a new variant of _TclpCreateTempFile_. TclpCreateTempFile: both Unix and Win version currently get a dumb C-style char-pointer with no length-information. They need two extra arguments, a length and the appropriate binary-bit. Since _TclpCreateTempFile_ is in the stubs-table, we definitely need a new Version of it, e.g. _TclpCreateTempFileEx_, which will take and use these new arguments. # Copyright This document has been placed in the public domain. |
Name change from tip/26.tip to tip/26.md.
|
| < | < | | | | | | | | | | > | | | | | | | | | 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 | # TIP 26: Enhancements for the Tk Text Widget Author: Ludwig Callewaert <[email protected]> Author: Ludwig Callewaert <[email protected]> State: Final Type: Project Vote: Done Created: 20-Feb-2001 Post-History: Discussions-To: news:comp.lang.tcl Obsoletes: 19 Tcl-Version: 8.4 ----- # Abstract This TIP proposes several enhancements for the Tk text widget. An unlimited undo/redo mechanism is proposed, with several user available customisation features. Related to this, a text modified indication is proposed. This means that the user can set, query or receive a virtual event when the content of the text widget is modified. And finally a virtual event is added that is generated whenever the selection changes in the text widget. # Rationale The text widget provides a lot of features that make it ideally suited to create a text editor from it. The vast number of editors that are based on this widget are a proof of this. Yet some basic features are missing from the text widget and need to be re-invented over and over again by the authors of the various editors. This TIP adds a number of the missing features. A first missing feature is an undo/redo mechanism. The mechanism proposed here is simple yet powerful enough to accommodate a very reasonable undo/redo strategy. It also provides sufficient user control, so that the actual strategy can be refined and tailored to the users need. A second missing feature is a notification if the text in the widget has been modified with respect to a reference point. [[19]](19.md) deals partly with this. This implementation takes it some steps further. First of all, there is a link with the undo/redo mechanism, since undoing or redoing changes can take you to or away from the reference point, and as such changes the modified state of the widget. Secondly, with this implementation, a virtual event is generated whenever the modified state of the widget changes, allowing the user to bind to that event and for instance give a visual indication of the modified state of the widget. Finally, a virtual event has been added that is triggered whenever the selection in the widget changes. At first it may seem not so useful, but there are a number of situations where this functionality is needed. A couple of examples where I ran into the need for this may clarify this. On Windows, if the text widget does not have the focus, the selection tag is not visible. This is consistent with other Windows applications. However, when implementing a search mechanism, the found string needs to be tagged with the selection tag. \(You want it to be selected\). The search \(and replace\) dialog box has the focus however, so this selection tag is invisible. To make it visible, another tag was used to duplicate the selection tag. This is very easy when the functionality described here is available. Otherwise it is very difficult to do this consistently. Another occasion was when I was implementing a rectangular cut and paste for the text widget. This was based on adding spaces on the fly, while selecting the rectangle. If for some reason the selection changes \(for instance on Unix another application gets the selection\) these spaces need to be removed again. Doing this is virtually impossible without this functionality. With it, it becomes trivial. The functionality itself adds little or no overhead to the text widget. # Specification The undo/redo mechanism operates by adding two stacks of edit actions to the text widget. Every insert or delete operation is added to the undo stack in normal operation. At certain times a separator is added onto the stack. All insert and delete actions in between two separators are considered to be one edit action, and will be undone or redone as one. The insertion of the separators is under user control. There is a |
︙ | ︙ | |||
97 98 99 100 101 102 103 | Currently only text inserts and deletes can be undone. All other changes to the widget, such as the adding or deleting of tags, cannot be undone. The modified state of the widget is implemented using a counter. Every insert or delete action, and every time such an action is redone, increments this counter. Every undone insert or delete decrements this counter. The widget is considered to be modified if the counter is not | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | < < > > | | | | | | | | | | < < > > | | | | | | < < < > > > | | | | | < < > > | | | | | | | | | | | | | | | | | | | | | < < > > | | | | | | | | | | < > | | | | | | | | | | | | | < > | | | | | | | | | < > | | | | | < < > > | | | | | | | < < > > | | | | | | > | 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 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 | Currently only text inserts and deletes can be undone. All other changes to the widget, such as the adding or deleting of tags, cannot be undone. The modified state of the widget is implemented using a counter. Every insert or delete action, and every time such an action is redone, increments this counter. Every undone insert or delete decrements this counter. The widget is considered to be modified if the counter is not zero. A virtual event _<<Modified>>_ is generated whenever this counter changes from zero to non-zero or vice versa. A mechanism is provided to reset the counter to zero. The modified state can also be explicitely set by the user. In that case, the counter mechanism is not operational until the modified state has been reset again. 1. _pathName configure -undo 0\|1_ - this enables or disables the undo/redo mechanism. The default is zero. 2. _pathName configure -autoseparators 0\|1_ - when one inserts a separator automatically whenever insert changes to delete or vice versa. Separators are also inserted when the keyboard or the mouse is used to move the insert mark, or when the <Return> key is pressed. When off, no separators are inserted, except by the user \(See 6\). The default is one. 3. _pathName edit undo_ - undoes the last edit action if undo is enabled \(See 1\). The insert mark will be positioned at the last undone edit action. When undo deletes text, that is the index where the text was. When undo inserts text, the insert mark will be positioned at the end of the inserted text. The view will be adapted to make the insert mark visible. Raises an exception if there is nothing to undo. Does nothing if undo is disabled. 4. _pathName edit redo_ - redoes the last edit action if undo is enabled \(See 1\). The insert mark and widget view will be updated similar to what is done for the edit undo command. Raises an exception if there is nothing to redo. Does nothing if undo is disabled. 5. _pathName edit reset_ - resets the undo and redo stacks \(clears them\). 6. _pathName edit separator_ - inserts a separator on the undo stack, indicating an undo boundary. If a separator is already present, this will do nothing. This means that it is safe to issue the command several times, without any inserts or deletes occurring in between. 7. _pathName edit modified ?boolean?_ - If boolean is not specified returns the modified state of the widget \(either 1 or zero\). If boolean is specified, sets the modified state of the widget to that value. 8. _<<Modified>>_ - this virtual event is generated whenever the modified state of the widget changes from modified to not modified or vice versa. 9. _<<Selection>>_ - this virtual event is generated whenever the range tagged with the selection tag changes. 10. _<<Undo>>_ - this virtual event calls pathName edit undo. 11. _<<Redo>>_ - this virtual event calls pathName edit redo. 12. _<Control-z>_ - is bound to the <<Undo>> virtual event. 13. _<Control-Z>_ - is bound to the <<Redo>> virtual event on all platforms except Win32. 14. _<Control-y>_ - is bound to the <<Redo>> virtual event on Win32. # Example The following code illustrates how the new features are intended to be used. global fileName global modState global undoVar set fileName "None" set modState "" set undoVar 0 text .t -background white -wrap none # Example 1: The Modified event will update a text label bind .t <<Modified>> updateState # Example 2: The Selection event will create a tag that # duplicates the selection bind .t <<Selection>> duplicateSelection frame .l label .l.l -text "File: " label .l.f -textvariable fileName label .l.m -textvariable modState grid .l.l -sticky w -column 0 -row 0 grid .l.f -sticky w -column 1 -row 0 grid .l.m -sticky e -column 2 -row 0 grid columnconfigure .l 1 -weight 1 frame .b button .b.l -text "Load" -width 8 -command loadFile button .b.s -text "Save" -width 8 -command saveFile button .b.i -text "Indent" -width 8 -command blockIndent checkbutton .b.e -text "Enable Undo" -onvalue 1 -offvalue 0 -| | variable undoVar trace variable undoVar w setUndo button .b.u -text "Undo" -width 8 -command "undo" button .b.r -text "Redo" -width 8 -command "redo" button .b.m -text "Modified" -width 8 -command ".t edit modified on" grid .b.l -row 0 -column 0 grid .b.s -row 0 -column 1 grid .b.i -row 0 -column 2 grid .b.e -row 0 -column 3 grid .b.u -row 0 -column 4 grid .b.r -row 0 -column 5 grid .b.m -row 0 -column 6 grid columnconfigure .b 0 -weight 1 grid columnconfigure .b 1 -weight 1 grid columnconfigure .b 2 -weight 1 grid columnconfigure .b 3 -weight 1 grid columnconfigure .b 4 -weight 1 grid columnconfigure .b 5 -weight 1 grid .l -sticky ew -column 0 -row 0 grid .t -sticky news -column 0 -row 1 grid .b -sticky ew -column 0 -row 2 grid rowconfigure . 1 -weight 1 grid columnconfigure . 0 -weight 1 proc updateState {args} { global modState # Check the modified state and update the label if { [.t edit modified] } { set modState "Modified" } else { set modState "" } } proc setUndo {args} { global undoVar # Turn undo on or off if { $undoVar } { .t configure -undo 1 } else { .t configure -undo 0 } } proc undo {} { # edit undo throws an exception when there is nothing to # undo. So catch it. if { [catch {.t edit undo}] } { bell } } proc redo {} { # edit redo throws an exception when there is nothing to # undo. So catch it. if { [catch {.t edit redo}] } { bell } } proc loadFile {} { set file [tk_getOpenFile] if { ![string equal $file ""] } { set fileName $file set f [open $file r] set content [read $f] set oldUndo [.t cget -undo] # Turn off undo. We do not want to be able to undo # the loading of a file .t configure -undo 0 .t delete 1.0 end .t insert end $content # Reset the modified state .t edit modified 0 # Clear the undo stack .t edit reset # Set undo to the old state .t configure -undo $oldUndo } } proc saveFile {} { # The saving bit is not actually done # So the contents in the file are not updated # Saving clears the modified state .t edit modified 0 # Make sure there is a separator on the undo stack # So we can get back to this point with the undo .t edit separator } proc blockIndent {} { set indent " " # Block indent should be treated as one operation from # the undo point of view # if there is a selection if { ![catch {.t index sel.first} ] } { scan [.t index sel.first] "%d.%d" startline startchar scan [.t index sel.last] "%d.%d" stopline stopchar if { $stopchar == 0 } { incr stopline -1 } # Get the original autoseparators state set oldSep [.t cget -autoseparators] # Turn of automatic insertion of separators .t configure -autoseparators 0 # insert a separator before the edit operation .t edit separator for {set i $startline} { $i <= $stopline} {incr i} { .t insert "$i.0" $indent } .t tag add sel $startline.0 "$stopline.end + 1 char" # insert a separator after the edit operation .t edit separator # put the autoseparators back in their original state .t configure -autoseparators $oldSep } } proc duplicateSelection {args} { .t tag configure dupsel -background tomato .t tag remove dupsel 1.0 end if { ![catch {.t index sel.first} ] } { eval .t tag add dupsel [.t tag ranges sel] } } # Reference Implementation <http://www.cs.man.ac.uk/fellowsd-bin/TIP/26.patch> _The patch has received little testing so far, so any testing is encouraged._ # Copyright This document has been placed in the public domain. |
Name change from tip/260.tip to tip/260.md.
|
| < | | | | | | < | | > | | | | | | | | | | | | | | | | | > | 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 | # TIP 260: Add Underline Option to Canvas Text Items State: Final Type: Project Tcl-Version: 8.5 Vote: Done Post-History: Author: Donal K. Fellows <[email protected]> Created: 04-Jan-2006 ----- # Abstract This TIP proposes adding an **-underline** option to the Tk **canvas** widget's text items. # Rationale If you're simulating a **label** \(or **button** or ...\) widget using a **canvas**, it is useful to be able to underline a single character of a piece of text. Although this can be done in various ways using **font measure** to work out where to start drawing, it would be far easier if we could use Tk's own built-in underlining engine \(which also gets other font-related issues correct too, and correcting for them is more difficult than it ought to be given that Tk already knows what to do anyway\). # Proposed Change The **canvas** widget's text items shall gain an additional option, **-underline** which shall take an integer value \(-1 being the default "no underline" value\) describing which character position in the text to underline, just as with the **-underline** option provided by the **label** widget \(and elsewhere\). As with all canvas items, no specific support for modification through the option database shall be provided, but otherwise the option shall be exactly as described in the **options** manual page. # Copyright This document has been placed in the public domain. |
Name change from tip/261.tip to tip/261.md.
|
| < | < | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 261: Return Imported Commands from [namespace import] Author: Martin Lemburg <[email protected]> Author: <[email protected]> State: Final Type: Project Vote: Done Created: 20-Dec-2005 Post-History: Tcl-Version: 8.5 ----- # Abstract This TIP describes a mechanism for easily finding out the list of commands in the current namespace that have been imported from other namespaces. # Rationale While writing a profiling and introspection module for our C\+\+/Tcl application, I searched for ways to query all the exported and imported commands of a namespace. Although I found the introspection functionality for discovering all exported commands of a namespace using **namespace export** in the exporting namespace, I found no way to query all imported commands inside the importing namespace. The documentation of **namespace import** said nothing about the behaviour, if no arguments were given, and testing **namespace import** without arguments resulted in nothing, in a no-op. Prompted by this, I started a thread in news:comp.lang.tcl which goes into more detail <http://groups.google.com/group/comp.lang.tcl/browse_frm/thread/9fb246cf65aba54f?tvc=1> . What seems to be more logical to me would be to change the no-op behaviour of **namespace import** to be comparable to **namespace export**, and return all imported commands inside the namespace **namespace import** is executed in. As an example... * to get all exported commands of a namespace ::exportingNspc: namespace inscope ::exportingNspc {namespace export} * to get all imported commands of the namespace ::importingNspc: namespace inscope ::importingNspc {namespace import} # Consequences The only consequence I know is, that old scripts using the no-op **namespace import** suddenly will return a list, probably filled with names of imported commands. That's all. Because of the fact, that **namespace import** never returned values, no script should really break, thus no script should require values from this command. # Proposed Change The result of **namespace import** without arguments shall be a list of all commands that have been imported into the current namespace. Each command in the list will be the simple name by which the command is known in the current namespace. This format for the returned value is most useful because it composes well with **namespace forget**. To remove all imported commands from a namespace, use the command namespace forget {*}[namespace import] # Implementation A patch implementing an earlier draft is available, <http://sf.net/tracker/?func=detail&aid=1437008&group_id=10894&atid=310894> , and updated patches will be attached to the same Tracker report. # Copyright This document has been placed in the public domain. |
Name change from tip/262.tip to tip/262.md.
|
| < | < | | | | | | | | | > | | | | | | | | | | | | | | | | > | 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 | # TIP 262: Background Images for Frames Author: Eric Taylor <[email protected]> Author: Donal K. Fellows <[email protected]> State: Draft Type: Project Vote: Pending Created: 18-Mar-2006 Post-History: Keywords: Tk,option Tcl-Version: 8.7 ----- # Abstract This TIP proposes an option for frames that allows users to set the background of the window to be an image. # Rationale Just a there is an **-image** option for **button** widgets, this TIP suggests that a **-backgroundimage** option for frames be implemented. The image should be either an entire single image, or a smaller image that would be tiled, with a **-tile** option. Tiling would repeat, as needed, a smaller image to fit the visible area of the frame. If the image was tiled, then it should be re-tiled as needed during a resize. The image would reside behind any other decoration or other widgets that resided in the frame. The image should be re-configurable to replace the image and/or remove it, as with a button image. This TIP should allow some rather classy looking tcl/tk programs to be created with much ease. # Proposed Change Two new options are proposed for **frame** widgets, to be manipulated using the normal **configure** and **cget** methods: * **-backgroundimage** _imageName_ - This gives the name of an image \(as created by **image create**\) that is to be painted onto the widget immediately after the painting of the solid background colour. If _imageName_ is the empty string \(the default\) no image will be painted. The painting of the image will be controlled by the **-tile** option. * **-tile** _boolean_ - If this option gives _boolean_ as true, the image will be painted such that the top-left corner corresponds to the top-left corner of the frame, and then subsequently repeatedly painted \(with no gaps between the areas painted\) to the right and below that initial painting until such time as the entire widget is covered by copies of the image. If this option gives _boolean_ as false, the image will only be painted once, such that the center of the image painted is coincident with the center of the frame widget. # Copyright This document has been placed in the public domain. |
Name change from tip/263.tip to tip/263.md.
|
| < | < | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | < > | | | | < > | | | | | < | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | < > | | | | | | | | | | | | | < > | | | | < > | | | | | | | | | | | | < > | | | | | | | < | > | | | | | | | < > | | | | | | | | < > | | | | < > | | | | < > | | | | | | | | | < > | > | 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 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 | # TIP 263: Quantum Tcl Author: Lars Hellström <[email protected]> State: Draft Type: Project Vote: Pending Tcl-Version: 9.2 Created: 01-Apr-2006 Post-History: ----- # Abstract A new Tcl command **qubit** is proposed. This command makes it possible to handle quantum information in the form of qubits. # Rationale As stated in [[131]](131.md), what Tcl needs in order to succeed in the marketplace is a feature that no other programming language provides, a "killer app" as it were. The Tk toolkit, Expect, cross-platform portability, starkits, tkcon, and excellent embed/extend-ability with respect to other languages are all well and good, but they have clearly failed to push Tcl usage to the point of having critical mass. The **qubit** command makes it possible to achieve an exponential speedup for important problems and should therefore provide a powerful enough incentive that even Perl programmers would be compelled to switch languages. # Background Quantum computing makes use of phenomena in quantum mechanics to, at each time step, carry out an exponential amount of work using only a linear amount of hardware. The way this maps onto physical reality is pretty mind-boggling, but for the programmer it is sufficient to think of the Quantum Processing Unit \(QPU\) as an extremely powerful but somewhat specialised coprocessor and leave it at that. \(Chances are anyway that the QPU isn't physically located in your desktop computer, as they tend to involve lots of lasers, magnets, vacuum chambers, liquid nitrogen cooling, etc.\) Quantum information display an interesting duality in that it is analog during a computation, but becomes digital as soon as one measures it. \(Wave/particle duality, in case anyone came to think of that, is the kind of "mapping onto physical reality" issue that will not be treated here.\) This makes the design of quantum algorithms somewhat different from the design of classical algorithms, in a manner similar to that in which the design of analog electronic circuits is different from the design of digital electronic circuits, as one must often work out the numbers rather than rely on a discrete case-by-case analysis. Another curious feature is that all fully quantum operations must be reversible, which in particular has the effect that quantum information can neither be duplicated nor \(in the absence of measurements\) destroyed, only rearranged. There is in particular no quantum analogue to assignments such as [set a $b], since not only need this copy the value of b, it also irrecoverably destroys the old value of a; the closest one gets to such an assignment is exchanging the values of a and b. For more information on quantum computing in general, see e.g.: * Wikipedia article "Quantum computer" <http://en.wikipedia.org/wiki/Quantum_computer> . * J. Gruska: Quantum Computing \(1999\), ISBN 0-07-709503-0, <http://www.fi.muni.cz/usr/gruska/quantum/> . # Specification The quantum computing model supported by the **qubit** command is that of _quantum bits_ \(more commonly called _qubits_\) and _quantum boolean circuits_. While other more fancy models such as "Quantum Turing Machines" exist, this is generally considered to be the most realistic model, and it is also the one most closely related to the number-of-gates complexity measure for classical computing. Should it in the future prove desirable to support also some other model, then one may do so through a separate command. In this model, a quantum state of N qubits is completely specified by a set of 2\*\*N complex numbers, usually known as _probability amplitudes_ \(they are not probabilities as such, but they do completely determine the probabilities for various events\). Many different bases are possible, but in the standard \(also known as the computational\) basis each of these amplitudes corresponds to a particular assignment of 0s and 1s to the qubits. Operations on a quantum state can be understood as operations on the vector of amplitudes. The **qubit** command has the five subcommands. ## The 'new' Subcommand > **qubit new** ?_-option value_ ?...?? Allocate/create a new qubit, and return a handle for the new qubit that identifies it in subsequent operations, or throw an error if allocation/creation failed \(possible causes include, but are not limited to, lack of resources on the hardware side and user having insufficient permissions\). New qubits are not entangled with any of the old ones, but their state is otherwise unspecified. The options are meant as a means for supplying extra information about the new qubit, such as for example whether it is being protected from decoherence by a scheme of quantum error correction codes \(the Tcl core can easily implement such features on platforms where the C level APIs only provide raw qubits\); however at present no options are defined. ## The 'operate' Subcommand > **qubit operate** _gate id0_ ?_id1_ ?...?? Perform a quantum operation \(the _gate_\) on one or more qubits \(specified using the handles _id0_, _id1_, etc.\). Returns the operation actually applied. In the interest of generality, gates are specified as unitary matrices \(this is a universal representation for quantum gates\), or more concretely as lists of lists of lists of doubles. The innermost lists must have length 2 and encode the real \(index 0\) and imaginary \(index 1\) parts of an element of the matrix. Indices in the middle list level select a column and indices in the outer list level consequently a row. Put another way, lindex $gate $i $j 0 ; # Returns Re gate(i,j) lindex $gate $i $j 1 ; # Returns Im gate(i,j) The row/column index corresponding to the _id0_ qubit having value $r0, the _id1_ qubit having value $r1, etc. is $r0\*\(2\*\*0\) \+ $r1\*\(2\*\*1\) \+ ... A _gate_ for operating on _n_ qubits must thus have side 2\*\*_n_. Columns correspond to qubit states before the operation and rows correspond to qubit states after the operation. An error is thrown if the number of qubit arguments does not match the side of the _gate_ matrix, if not all _idN_ arguments are qubit handles, if some qubit occurs twice in the list, and if _gate_ is not a proper matrix \(too many or too few elements in some list, elements not recognised as doubles, etc.\). An error is _not_ thrown if the _gate_ is not unitary. In general the operation actually applied has to be supported by the available hardware, so the **qubit operate** command \(or some lower level interface\) should determine which supported operation most closely approximates the specified _gate_ and apply that instead. The user can check what was done \(up to numeric precision\) by inspecting the return value. Using a return value from **qubit operate** as the _gate_ for another call should result in the exact same operation being carried out. ## The 'measure' Subcommand > **qubit measure** _id_ Measures a qubit with respect to the standard basis. Returns 0 or 1 depending on the resulting state. _Note_ that measuring a qubit changes the quantum state to one in which that qubit has a pure value. If other qubits are initially entangled with the one being measured, then these will also be affected by this operation. Measuring a qubit causes it to be disentangled from all other qubits \(or perhaps entangles the state of the entire universe with the qubit, depending on your philosophical point of view\). ## The 'dispose' Subcommand > **qubit dispose** _id_ Frees/deallocates a qubit, returning it to whatever pool of resources **qubit new** got it from, but before doing that the qubit is measured to safely disentangle it from any remaining qubits. The return value is 0 or 1 as for the corresponding **qubit measure**. ## The 'names' Subcommand > **qubit names** This is an instrospection command. It returns a list of all qubit handles currently available in this interpreter. ## Future Expansion Other subcommands may be added in the future, but this set is complete for single interpreter algorithms. # Examples The syntax of **qubit operate** was chosen to facilitate the creation of aliases for common gates, as this should make programs more readable. An alias for the CNOT \(conditional not\) gate can be created as interp alias {} CNOT {} qubit operate { { {1 0} {0 0} {0 0} {0 0} } { {0 0} {0 0} {0 0} {1 0} } { {0 0} {0 0} {1 0} {0 0} } { {0 0} {1 0} {0 0} {0 0} } } after which one can use the command CNOT $control $target The more significant $target qubit is negated if the $control qubit is 1 but left alone otherwise. Another standard gate is the Hadamard gate, which can be defined as follows. set rsqrt2 [list [expr {1/sqrt(2)}] 0] ; # Reciprocal square root of 2. interp alias {} Hadamard {} qubit operate [ list [list $rsqrt2 $rsqrt2] [list $rsqrt2 [list [expr -sqrt(0.5)] 0]] ] The Hadamard gate is used to create states that are uniform superpositions of 0s and 1s. A simple application of that is the following random bit generator. proc randombit {} { set id [qubit new] ; # Allocate qubit qubit measure $id ; # Make pure 0 or pure 1 Hadamard $id ; # Make an equal mix of 0 and 1 return [qubit dispose $id]; # Measure and clean up } Note that this \(provided, of course, that one believes in the standard interpretation of quantum mechanics\) is not a psuedo-random bit generator, but a truly random bit generator. Even if the Hadamard gate would be slightly off \(unlikely, as this is a very standard gate, but possible\) this would not affect the essential randomness of the bits produced, but only the exact probability. A third type of elementary gate is the phase shift gate, which changes the phase \(but not the size\) of some probability amplitude. To change the phase of the 1 amplitude of a qubit $id by the angle $phi, one would use the command qubit operate [list {{1.0 0.0} {0.0 0.0}} [list {0.0 0.0} [ list [expr {cos($phi)}] [expr {sin($phi)}] ]]] $id Phase changes do not change the probability distribution for any qubit measurement, but they do affect the state in ways that can lead to different probabilities further on, and thus illustrate the fact that there is more to a quantum state than the probability distribution it gives rise to here and now. As a concrete example of this, assuming $id is a qubit, and with aliases as above, the script: set before [qubit measure $id] Hadamard $id Hadamard $id set after [qubit measure $id] expr {$before == $after} will with probability 1 produce the result 1, whereas the script: set before [qubit measure $id] Hadamard $id qubit operate {{{1 0} {0 0}} {{0 0} {-1 0}}} $id Hadamard $id set after [qubit measure $id] expr {$before == $after} will with probability 1 produce the result 0. The only difference is the 180 degrees phase shift of the 1 amplitude in the explicit **qubit operate** command, which transforms one state with equal probabilities for 0 and 1 to another state with equal probabilities for 0 and 1! # Rejected Alternatives One might expect that a truly Quantum Tcl would keep quantum information as "first class data", i.e., in Tcl\_Objs to be passed around by value rather than as qubits that can only be passed around by name, but that is impossible \(unless one goes to such lengths as to run the entire Tcl process in a QPU, which again will probably never be possible\) due to a fundamental incompatibility between the laws of quantum mechanics and Tcl's Everything Is A String principle. Beginning with the EIAS side, one may observe that for a quantum state to be encodable into a Tcl\_Obj, it must be serializable - there must be a way of generating a string that completely encodes the state. Since quantum mechanics does not permit extracting that much information about a quantum state, there are only two options: either everything is kept within the QPU \(not realistic\), or nothing is kept in the QPU. In the latter case, one loses entirely the advantage of quantum computation, so it is rather pointless. On the quantum side, one may observe that most of the things that are routinely done to Tcl\_Objs are simply impossible to do to quantum information. The fundamental problem here is that Tcl\_Objs must be duplicatable, whereas it is a theorem in quantum mechanics that quantum states cannot be duplicated \(the "No cloning" theorem\). Somewhat related is the problem that quantum information can only be read \(used as input to some operation\) once, whereas a Tcl\_Obj can be written once but read an unlimited number of times. # Security Implications As the **qubit** command only manipulates data and cannot be used for any form of communication, it may in principle be made available also in safe interpreters. However since **qubit new** seizes a global resource that can be expected to be in limited supply on a system, it is probably better to be safe than sorry, and therefore the **qubit** command shall initially be hidden in a safe interpreter. Omitting the command entirely and instead alias all qubit operations to the **qubit** command of the parent interpreter is _not_ a good idea, as the quick \(but sloppy\) implementation of this would allow untrusted code evaluated in the safe interpreter access also to the qubits of the parent. It should be noted that the easy access to quantum computing that this command provides would have significant implications for the security of many external systems. Such issues are outside the scope of this TIP. # Future Extensions Besides quantum algorithms, many interesting applications of quantum information processing involves communication through the means of a quantum state shared by different parties. While fast long distance qubit transportation is physically made possible by means of quantum teleportation \(which really isn't as fancy as it sounds - basically it amounts to a combination of the old TV chef trick of having prepared something in advance, in this case physically transferring a qubit, and the patchfile trick of only transmitting a diff against what was physically distributed\), there are currently no standardised protocols for this, and until the time that there is there probably isn't much point in specifying some **qubit socket** command for Tcl either. It may however be observed that _non-open_ commercial systems <http://www.magiqtech.com/> transmitting quantum information over long distances are available today. While transferring qubits between different machines obviously present some technical problems, it may seem that transferring qubits between different interpreters in the same process should at least be straightforward, but the presence of multiple threads in the process introduce complications also for this case. Concretely, transferring a qubit from one thread to another will in general cause these threads to become entangled! In order to not make thread maintenance even more complicated by introducing the concept of quantum deadlock due to thread tangles, this TIP does not treat the subject of a mechanism for transferring qubits between interpreters. # Reference Implementation A Tcl level emulation of the **qubit** command \(minus some error checking, but also not requiring a QPU\) is available as SF patch no 1462755 <http://sf.net/tracker/?func=detail&aid=1462755&group_id=10894&atid=310894> . This emulation uses the standard Tcl rand\(\) function for generating random numbers, so it is not cryptographically safe. Also note that it internally uses of some tcllib packages, which must therefore be available. No C implementation exists at present, but creating one is a simple matter of programming \(SMOP\). In particular, since the details of the command implementations for the foreseeable future almost surely will have some dependence on the particular hardware present, it seems appropriate to assign to each subcommand an entry in the internal stubs table and then simply have the main _Tcl\_QubitObjCmd_ call each as appropriate. int Tcl_QubitObjCmd( ClientData clientData, /* Might be used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *CONST objv[]) /* Argument objects. */ { int index; static CONST char *options[] = { "dispose", "measure", "names", "new", "operate", (char *) NULL }; enum options { QUBIT_DISPOSE, QUBIT_MEASURE, QUBIT_NAMES, QUBIT_NEW, QUBIT_OPERATE }; if (objc < 2) { Tcl_WrongNumArgs(interp, 1, objv, "subcmd ?arg ...?"); return TCL_ERROR; } if (Tcl_GetIndexFromObj(interp, objv[1], options, "subcommand", 0, &index) != TCL_OK) { return TCL_ERROR; } switch ((enum options) index) { case QUBIT_DISPOSE: return TclQubitDisposeObjCmd(clientData, interp, objc, objv); case QUBIT_MEASURE: return TclQubitMeasureObjCmd(clientData, interp, objc, objv); case QUBIT_NAMES: return TclQubitNamesObjCmd(clientData, interp, objc, objv); case QUBIT_NEW: return TclQubitNewObjCmd(clientData, interp, objc, objv); case QUBIT_OPERATE: return TclQubitOperateObjCmd(clientData, interp, objc, objv); } /* * We won't get this far. */ Tcl_Panic("unhandled subcommand"); return TCL_ERROR; } A fallback definition of _TclQubitNewObjCmd_ that can be used when Tcl is compiled without hardware QPU support is: int TclQubitNewObjCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *CONST objv[]) /* Argument objects. */ { int optArgIdx, index; static CONST char *optionStrings[] = { (char *) NULL /* Currently there are no options. */ }; if (objc % 2 != 0) { Tcl_WrongNumArgs(interp, 2, objv, "?-option value ...?"); return TCL_ERROR; } for (optArgIdx = 2 ; optArgIdx < objc ; optArgIdx += 2) { if (Tcl_GetIndexFromObj(interp, objv[optArgIdx], optionStrings, "option", TCL_EXACT, &index) != TCL_OK) { return TCL_ERROR; } /* * When options are added, handle them here. */ } /* * Fail gracefully. */ Tcl_SetErrno(ENXIO); /* QPU not configured. */ Tcl_AppendResult(interp, "couldn't allocate a qubit: ", Tcl_PosixError(interp), NULL); return TCL_ERROR; } Other fallback definitions obviously follow the same pattern. Filling in the details should be a cultivating exercise for Robert Abitbol. # Copyright This document has been placed in the public domain. |
Name change from tip/264.tip to tip/264.md.
|
| < | | | | | | < | | | > | | | | | | | | | | | | | < > | < | > | > | 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 | # TIP 264: Add Function to Retrieve the Interpreter of a Window State: Final Type: Project Tcl-Version: 8.5 Vote: Done Post-History: Author: George Petasis <[email protected]> Created: 01-Apr-2006 Keywords: Tk, C API ----- # Abstract This TIP proposes the addition of a new function in the Tk public API, for retrieving a pointer to the Tcl interpreter that was used for creating a window. # Rationale During the development of a Tk extension that adds a ClientMessage handler under unix \(tkdnd\), I needed to get the pointer of the Tcl interpreter that is associated with a window. When the ClientMessage handler is called, only a Tk\_Window pointer is passed, for the window the ClientMessage is for. But if you want to execute Tcl code, you don't have a Tcl interpreter... Of course, you can try use any \(cached\) interpreter, but this can lead to various problems, if it is not the interpreter that was used for creating the window. Since Tk already has this information, adding a function to return the associated interpreter for a Tk\_Window pointer will be relatively easy. # Proposed Change A new public function \(with signature _Tcl\_Interp \*_ **Tk\_Interp**_\(Tk\_Window tkwin\)_\) is proposed to be added to the public C API of Tk. This function can be implemented as follows: Tcl_Interp * Tk_Interp(Tk_Window tkwin) { if (tkwin != NULL && ((TkWindow *) tkwin)->mainPtr != NULL) { return ((TkWindow *) tkwin)->mainPtr->interp; } return NULL; } # Copyright This document has been placed in the public domain. |
Name change from tip/265.tip to tip/265.md.
|
| < | < | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | < > | | | | | | | | | | | | | | | | | | | | | | | < > | | | | | | | | | | | | < | > | > | 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 | # TIP 265: A Convenient C-side Command Option Parser for Tcl Author: Sam Bromley <[email protected]> State: Final Type: Project Vote: Done Created: 03-Apr-2006 Post-History: Tcl-Version: 8.6 Keywords: Command line parsing, C implementation ----- # Abstract The Tk C library provides developers with a _Tk\_ParseArgv_\(\) function that allows command line parsing of options of the "-option" form. Archived discussions on news:comp.lang.tcl and on the Wiki indicate that a desire for similar functionality without Tk has arisen several times in the past. This TIP presents a Tk-free implementation of _Tk\_ParseArgv\(\)_ named **Tcl\_ParseArgvObj**, that developers can use to parse "-option" style command options in C implementations of Tcl commands using the Tcl\_Obj interface. # Rationale While the parsing of command options can be readily accomplished on the Tcl side, a uniform method for parsing "-option" formed options does not exist on the C side. Many developers are familiar with the ease of use of libpopt-style command line parsing, but a similarly clean method does not currently exist in Tcl. The common approach is to use _Tcl\_GetIndexFromObj_\(\), yet this method alone does not allow the flexibilty and ease of use of libpopt-style parsing. One drawback of the classical _Tcl\_GetIndexFromObj_\(\)-only approach is the need to handle the specifies of your command option parsing for each unique command. This leads to significant code duplication. A libpopt-style approach is to bundle all of your parsing specifics into a single array of structures capturing the details, and then let a specific parsing routine handle the parsing of every option for you. The **Tcl\_ParseArgvObj**\(\) routine introduced in this TIP provides this functionality, thereby allowing the removal of all parsing specifics from the command implimentation other than that necessary to describe each optional argument. Additionally, a function **Tcl\_ParseArgsObjv** is provided to provide the functionality of _Tk\_ParseArgs_\(\) to those who desire it. A discussion in 2002 on news:comp.lang.tcl <http://groups.google.com/group/comp.lang.tcl/browse_thread/thread/c4fea8f0346cf8ae/036961bf476a3b99?q=tcl_parseargv&rnum=2#036961bf476a3b99> indicated that this is a desired feature. Arguments against a **Tcl\_ParseArgsObjv** implementation include that it is better to do all command line parsing on the Tcl side. However, this implies writing two wrapper functions: \(i\) A C implementation of a Tcl command; and \(ii\) A Tcl wrapper that pre-parses the options before calling the C command. This can lead to significant duplication of effort when porting a large project to a Tcl enabled version. This point is particularly relevent in the context of **Tcl\_ParseArgvObj**\(\), as then one is not assuming that one can simply replace the main\(\) routine with Tcl, but rather that one is truly embedding the C side in a larger system. **Tcl\_ParseArgvObj**\(\) offers a clean method to enable flexible command line parsing to C implementations of Tcl commands. # Specification This document proposes adding **Tcl\_ParseArgsObjv**, whose arguments shall be: > int **Tcl\_ParseArgsObjv**\(Tcl\_Interp \*_interp_, const Tcl\_ArgvInfo *_argTable_, int \*_objcPtr_, Tcl\_Obj \*const \*_objv_, Tcl\_Obj *\*\*_remainingObjv_\) **Note** that the count of arguments \(referred to by _objcPtr_\) will be modified, and a modified array will be returned via _remainingObjv_ \(and need **ckfree**ing\). The input array of objects will not be modified. # Reference Implementation A working implementation has been submitted to the Feature Request Tracker at SourceForge <https://sourceforge.net/support/tracker.php?&aid=1446696> . # Example of Use #include <tcl.h> #include <tclArgv.h> /* not needed if subsumed into core */ int g_test_cmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { char *gname,*filename; int i; int numRepeat; double scalar; int doErase = 0; size_t size; /* this table specifies the possible options, all in one place.*/ Tcl_ArgvInfo argTable[] = { {"-erase", TCL_ARGV_CONSTANT, (void *) 1, &doErase, "erase image before plotting"}, {"-numRepeat", TCL_ARGV_INT, NULL, &numRepeat, "number of times to repeat test"}, {"-scalar", TCL_ARGV_FLOAT, NULL, &scalar, "scalar multiple to use for test"}, {"-outfile", TCL_ARGV_STRING, NULL, &filename, "name of file to which to dump result"}, {NULL, TCL_ARGV_END, NULL, NULL, NULL} }; /* Call Tcl_ParseArgObjv to do all the parsing! */ if (Tcl_ParseArgsObjv(interp,argTable,&objc,objv,&private_objv) != TCL_OK) { return TCL_ERROR; } /* Should recheck objc here */ /* at this point, any unhandled options are repacked in private_objv */ gname = Tcl_GetString(private_obj[1]); /* all done */ ckfree(private_objv); /* rest of code continues here...*/ return TCL_OK; } # Copyright This document has been placed in the public domain. |
Name change from tip/266.tip to tip/266.md.
|
| < | < | | | | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 266: Numbers are Commands Author: Kristoffer Lawson <[email protected]> Author: Michal Malecki <[email protected]> Author: Wolf-Dieter Busch <[email protected]> Author: Paul Nash <[email protected]> State: Rejected Type: Project Vote: Done Created: 11-Apr-2006 Post-History: Keywords: Tcl,unknown,expression Tcl-Version: 8.5 ----- # Abstract This TIP describes a change to Tcl's command dispatch which would allow every number to act as a command. # Rationale Maths in Tcl are continuously a stumbling block. The **expr** command is ugly and cumbersome. It adds a new C-like syntax within Tcl and easily makes lines less readable, especially with the most common use of simple arithmetic. In addition it is confusing to the programmer to have to remember there is a completely separate set of commands, or functions, which are only available to the **expr** command. This proposal offers a clean solution which could eventually totally replace **expr**, yet offers few or no backward compatibility problems and fits in with the Tcl philosophy of "every piece of executable code is a command". This addition is easy to build as a separate extension using the mechanisms provided by Tcl. However, this will not be widely used unless it is stamped as part of the language and part of its unique philosophy. In addition, implementations in the core can gain from many forms of optimisation that would not be possible with a normal extension. There is an existing proposal for making operands into commands. That proposal is still a valid one, but the description in this TIP leads to syntax which will be more familiar to most programmers. It does not have operator precedence, which is a difference from normal mathematics, but one that should be easier to grasp than the reversed notation that operator commands offer. In fact, there are many claims which state operator precedence is a mistake anyway. # Specification Every number that can be handled by Tcl is a command. The format for number commands is: > _number_ _operation_ ?_arg1 arg2 ..._? For example: 8 * 5 + 2 The first argument must be an operator, and can be one of any specified for the **expr** command \(\+, -, \*, /, ...\) Subsequent arguments can be either numbers or operators. The command evaluates its arguments from left-to-right \(no precedence\) with the result of the left used as the operand for the next operation. _e.g._ to get 242 a simple addition can be made: 200 + 42 If multiple numbers are given without operators between them, the last operator is used. _e.g._ for the result "42" the following can be used: 20 + 10 10 2 To get "23", the following can be used: 20 + 10 10 2 / 2 + 2 Normal Tcl brackets can be used for grouping purposes. _e.g._ the result "31337" can be reached with the following: 62674 / [1 + 1] Number commands act just like any other commands in Tcl. They can be nested with brackets, aliased, replaced and even removed. The only difference is that they do not appear in the list returned by **info commands**. However, any replacements made on them do. ## Compatibility Because of the ability to replace number-commands, there are no real backwards compatibility issues. There are very few, if any, extensions that make numbers into commands and any that do will still work with the only exception being software that would mix extensions that would depend on the functionality in this TIP and extensions that create their own commands which are only numbers. In any case, the author is not aware of any extensions that create commands in that manner. The only other area where incompatibilities would arise would be if someone is using an **unknown** mechanism which creates similar functionality to the one presented here. These extensions do exist, but are mostly presented as brain-twisters instead of for serious use. Additionally, Tcl does not and cannot guarantee that new commands will not appear in the global namespace. Indeed, every new release does this. For these reasons, this proposal can be implemented with a minor version bump. # Implementation Discussion The first natural step is to add a detection phase before the normal unknown mechanism. In fact, a prototype implementation can easily and trivially be built with Tcl's **unknown** command. The detection should work by checking if the unknown command is a number and if so, it will run the number command functionality. Otherwise, the normal Tcl chain of events is followed. If the command is replaced, this number mechanism is never reached, as a normal command exists to handle the situation. If the command is removed, a special flag should be set to specify that the number in question cannot be used as a command. At a later date, further integration with the bytecode engine can be made. The details of such optimizations are outside the scope of this TIP. Some may argue that it is not good to disable defining commands with numbers by users. For example, someone would like to "overload" 0 and 1 to use [!file exists $f] && \{ puts "File not found"; exit \}. This also does not look like a good solution for 'expr' command; this will be still not the same as expressions in other languages \(required spaces between operators etc.\) # Alternative Approaches Instead of allowing multiple number arguments to use the same operator, a requirement could be made that every other argument must be an operator and every other one an operand. This might make the specification somewhat clearer, but would mean a mathematical operation on a list would not be as easy. # Comments This is a change to the "eleven rules", so please do not do it. It takes the possibility that I can do it myself by changing the procedure unknown. # Copyright This document has been placed in the public domain. |
Name change from tip/267.tip to tip/267.md.
|
| < | < | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 267: Allow 'exec' to Ignore Stderr Author: Nathan Bell <[email protected]> State: Final Type: Project Tcl-Version: 8.5 Vote: Done Created: 25-Apr-2006 Post-History: ----- # Abstract Currently the **exec** command will always fail if the process writes to standard error. Since various applications use stderr for debug output it would be useful to retain this output without having to resort to redirecting stderr to stdout \(which can cause interleaving\). # Rationale Various applications use stderr not just to report errors, but also warnings and debugging information. Right now, the only way to make such a program behave sensibly is to redirect stderr to stdout, or to a null device \(_i.e._, /dev/null\). If the program's output is being used elsewhere \(_i.e._, to generate a document\), stderr is the only means of reporting debugging or progress information to the user. This information is lost if a redirect is used. Since standard error can be safely ignored in such circumstances, **exec** is wrong to report such output as an error. Allowing **exec** to ignore stderr in those situations would be both beneficial and more correct. It should not be enabled by default though, as other applications write to stderr solely to indicate that an error occurred, and do not generate a non-zero exit code. # Consequences Many applications use stderr for debugging and error reporting. When a program fails, it will often return an error code and report the problem to stderr. If **exec** is ignoring stderr such a error report will also be ignored, leaving the tcl script with just the knowledge that some error occurred. If the script is being run in a terminal or on the console, the stderr will be reported directly to the user, but the script will have no way of getting the information. It is up to the user of **exec** to deal with this as appropriate. # Proposed Changes As **exec** already contains the ability to accept options, adding an option to ignore stderr is the most backward compatible fix. An option **-ignorestderr** would fit with the existing **-keepnewline** and proposed **-binary** \(see [[259]](259.md)\). # Implementation A patch exists in the SourceForge feature request section \(Request ID 1476191 <http://sf.net/tracker/?func=detail&aid=1476191&group_id=10894&atid=360894> \). This patch applies to generic/tclIOCmd.c. If the **-ignorestderr** option is given, _Tcl\_OpenCommandChannel_\(\) is not passed the TCL\_STDERR flag. This is the most straightforward method as it allows the existing functionality of _Tcl\_OpenCommandChannel_\(\) to be exposed to **exec** command. # Copyright This document has been placed in the public domain. |
Name change from tip/268.tip to tip/268.md.
|
| < | < | | | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | < > | | | < > | | | | | | < < < < < < < < < | > > > > > > > > > | | | | | | | < > | < | > | | < | > | | | | | | < > | | < > | | < < > > | | | | | | < > | | | < > | | | < > | | | | | | | < > | < > | | | < < > > | < | > | | | | | | | < > | < | > | | | < > | | | | | < > | < > | | | | | | | < > | | | < < < < < < < < < < < < < | | < < < | > > > > > > > > > > > > > > > > | > | 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 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 | # TIP 268: Enhance 'package' Version Handling Author: Jeff Hobbs <[email protected]> Author: Hemang Lavana <[email protected]> Author: Andreas Kupries <[email protected]> Author: Don Porter <[email protected]> State: Final Type: Project Vote: Done Created: 28-Apr-2006 Post-History: Tcl-Version: 8.5 ----- # Abstract This TIP proposes enhancing the Tcl **package** command to understand version numbers containing "a", and "b" and extend the semantics of **package require** to allow multiple requirements and various types of ranges of versions. # Rationale The current Tcl **package** command is limited to understanding package versioning based strictly on an infinite number of dot-separated positive integers. Regardless, Tcl extensions and the core itself use version numbers that have "a" for alpha and "b" for beta. This proposal seeks to make those identifiers properly understood by Tcl's **package version** semantics. It also extends the logic to allow ranges. This allows users to exclude package versions with known bugs/incompatibilities as well as accepting a range of major versions, which was previously only possibly through multiple **package require** calls and **catch**. The addition of **package prefer** is created to handle nuances in how the new package requirements mechanism interprets alpha/beta versions, because sometimes you want the bleeding edge version of a package, and other times you want something you can depend on. # Specification **Current version specification:** \(Summary of <http://www.tcl.tk/man/tcl8.4/TclCmd/package.htm\#M15\)> Version numbers consist of one or more decimal numbers separated by dots, such as 2 or 1.162 or 3.1.13.1. The first number is called the _major_ version number. Larger numbers correspond to later versions of a package, with leftmost numbers having greater significance. For example, version 2.1 is later than 1.3 and version 3.4.6 is later than 3.3.5. Missing fields are equivalent to zeroes: version 1.3 is the same as version 1.3.0 and 1.3.0.0, so it is earlier than 1.3.1 or 1.3.0.2. **Proposed version specification adds:** In addition, the letters 'a' \(alpha\) and/or 'b' \(beta\) may appear exactly once to replace a dot for separation. These letters semantically add a negative specifier into the version, where 'a' is -2, and 'b' is -1. Each may be specified only once, and 'a' or 'b' are mutually exclusive in a specifier. Thus 1.3a1 becomes \(semantically\) 1.3.-2.1, 1.3b1 is 1.3.-1.1. Negative numbers are not directly allowed in version specifiers. A version number not containing the letters 'a' or 'b' as specified above is called a _stable_ version, whereas presence of the letters causes the version to be called is _unstable_. The syntax of [package vsatisfies] is extended to > **package vsatisfies** _version requirement_ ?_requirement_ ...? where each _requirement_ is is allowed to have any of the forms: 1. min 1. min- 1. min-max where "min" and "max" are valid version numbers. The current syntax is case 1, and the addition of cases 2 and 3 does not interfere with keeping backward compatibility. These three forms are called, in the order as listed above: 1. "min-bounded" 1. "min-unbound" 1. "bounded" Given the above the **package vsatisfies** functions like this: * The version has to pass at least one of the listed requirements to be satisfactory. * A version satisfies a "bounded" requirement when > \* For min equal to the max if, and only if the version is equal to the min. > \* Otherwise if, and only if the version is greater than or equal to the min, and less than the max, where both min and max have been extended internally with 'a0'. NOTE: min is _inclusive_, max is _exclusive_. * A "min-bounded" requirement is a "bounded" requirement in disguise, with the max part implicitly specified as the next higher major version number of the min part. A version satisfies it per the rules above. * A version satisfies a "min-unbound" requirement if, and only if it is greater than or equal to the min, where the min has been padded internally with 'a0'. There is no constraint to a max. A new subcommand [package prefer] is added with syntax: > **package prefer** ?**latest**\|**stable**? With no arguments, **package prefer** returns either "latest" or "stable", whichever describes the current mode of selection logic used by **package require**. When passed the argument "latest", it sets the selection logic mode to "latest". When passed the argument "stable", if the mode is already "stable", that value is kept. If the mode is already "latest", then the attempt to set it back to "stable" is ineffective and the mode value remains "latest" [*]. When passed any other value as an argument, raise an invalid argument error. When a Tcl\_Interp is created, its initial selection mode value is set to "stable" unless the environment variable _TCL\_PKG\_PREFER\_LATEST_ is set. If that environment variable is defined \(with any value\) then the initial \(and permanent\) selection mode value is set to "latest". The syntax of **package require** is changed to: > **package require** ?**-exact**? _package_ ?_requirement_ ...? and its package selection logic is modified to both agree with **package vsatisfies** and to additionally support a multi-mode selection logic based on the result of **package prefer**. The requirements arguments are of the same form as accepted by **package vsatisfies**. The logic is: * In the "**stable**" selection mode the command will select the highest stable version satisfying the requirements, if any. If no stable version satisfies the requirements, the highest unstable version satisfying the requirements will be selected. This implements the behaviour that package require foo 1.5.3 > will load version 1.5.4 in preference to version 1.6b2. > By default package require foo 1.5b3 > will also load version 1.5.4 in preference to version 1.6b2, while still accepting 1.5b3 if it is the best available. It will also accept and load version 1.6b2 if no stable version that satisfies the requirement is available. > This fallback strategy employed for "**stable**", i.e. the ability to accept things outside of the declared preference makes programs combining several packages less fragile. This comes directly from implementing things as a preference to apply when possible, and not as a threshold that rejects nonpreferred, yet satisfactory solutions. * In the "latest" selection mode the command will accept the highest version satisfying all the requirements, regardless of its stableness. All other **package** subcommands that accept a version number argument are also revised to accept the expanded set of legal version numbers. The calls to _Tcl\_PkgProvide\(\)_ in both Tcl and Tk are revised to pass in TCL\_PATCH\_LEVEL and TK\_PATCH\_LEVEL where they currently pass in TCL\_VERSION and TK\_VERSION. **info tclversion**, **info patchlevel**, **$::tcl\_version**, **$::tcl\_patchLevel**, **$::tk\_version**, and **$::tk\_patchLevel** are left unchanged. A new public function _Tcl\_PkgRequireProc_ is provided, which has the signature: > int **Tcl\_PkgRequireProc**\(Tcl\_Interp \*_interp_, CONST char \*_name_, int _objc_, Tcl\_Obj \*CONST _objv_[], ClientData \*_clientDataPtr_\) This function implements **package require** at the C level. The existing functions _Tcl\_PkgRequire\(Ex\)_ are re-implemented in terms of this function. It returns a standard Tcl error code, leaving either an error message \(TCL\_ERROR\), or the version of the found package \(TCL\_OK\) in the result area of the _interp_ argument. The API between _Tcl\_PkgRequire\*_ and the package unknown handler is changed as well. The unknown handler now has the signature: > _unknown name_ ?_requirement..._? All existing unknown handlers \(init.tcl, tm.tcl\) are changed to this API. ## Examples Valid version numbers: 1.3a1 Invalid version numbers: 1.3a 1.3a1b2 1.3.a1 # Discussion Tcl RFE 219296 proposes similar support with the addition of a **threshold** method to **package**. This proposal operates by modelling the **a**, and **b** specifiers as negative version specifiers. A disadvantage of this proposal compared to the previous one is for folks trying to do integration testing of unstable packages. They will be required to take the additional step of either defining the environment variable TCL\_PKG\_PREFER\_LATEST or call package prefer latest in an initialization script in order to overcome the default preference that would otherwise fail to load the code that needs testing. It doesn't seem too great a burden, but anything that makes testing of untable packages more difficult means that on the margin there will be less testing of them. The impact of that is worth pondering a bit. An important thing made possible is the sequence: package provide Tcl 8.5a5 package require Tcl 8.5 so existing scripts with [package require Tcl 8.5] aren't broken by a Tcl 8.5a5 release. This support comes from the rules for interpreting a requirement's implicit demands beyond the fields it explicitly names. A requirement of 8.5 gets interpreted as equivalent to 8.5a0 and not equivalent to 8.5.0. Note the language about _internally extended with 'a0' _ in the rules of **package vsatisfies**. # Footnotes [*] Yes, this means **package prefer stable** is a verbose no-op. Sometimes a verbose no-op can help code readability. I also think documenting a setter/getter that is a no-op for some set values is easier than explaining why the set of valid returns from the getter differs from the set of acceptable arguments to the setter. Ability to do things like: interp create i i eval [list package prefer [package prefer]] is a factor here as well. Lots of discussion and rationale ensued on the tcl-core mailing list. Lars Hellström provided a good interpretive synopsis <http://aspn.activestate.com/ASPN/Mail/Message/tcl-core/3214264> . # Reference Implementation C implementation, see SF Patch 1520767<http://sourceforge.net/support/tracker.php?aid=1520767> . A reference implementation written in Tcl now follows. proc intList {version} { # Convert a version number to an equivalent list of integers # Raise error for invalid version number if {$version eq {} || [string match *-* $version]} { # Reject literal negative numbers return -code error "invalid version number: \"$version\"" } # Note only lowercase "a" and "b" accepted and only one if {[llength [split $version ab]] > 2} { return -code error "invalid version number: \"$version\"" } set converted [string map {a .-2. b .-1.} $version] set list {} foreach element [split $converted .] { if {[scan $element %d%s i trash] != 1} { # Require decimal formatted numbers with no suffix return -code error "invalid version number: \"$version\"" } if {[catch {incr i 0}] || $i < -2 } { # Verify each component is integer >= -2 return -code error "invalid version number: \"$version\"" } lappend list $i } return $list } proc compare {l1 l2} { # Compare lists of integers foreach i1 $l1 i2 $l2 { if {$i1 eq {}} {set i1 0} if {$i2 eq {}} {set i2 0} if {$i1 < $i2} {return -1} if {$i1 > $i2} {return 1} } return 0 } proc {package vcompare} {v1 v2} { compare [intList $v1] [intList $v2] } proc {package vsatisfies} {v args} { set vList [intList $v] ;# verify valid version number foreach requirement $args { ;# check all valid requirements if {[llength [lassign [split $requirement -] min max]]} { # More than one "-" return -code error "invalid requirement: \"$requirement\"" } if {[catch {intList $min}]} { return -code error "invalid requirement: \"$requirement\"" } if {$max ne "" && [catch {intList $max}]} { return -code error "invalid requirement: \"$requirement\"" } } foreach requirement $args { lassign [split $requirement -] min max set minList [intList $min] lappend minList -2 if {[compare $vList $minList] < 0} { continue ;# not satisfied; on to the next one } if {[string match *- $requirement]} { # No max constraint => satisfied! return 1 } if {$max eq ""} { set max [lindex $minList 0] incr max } set maxList [intList $max] lappend maxList -2 if {[compare $minList $maxList] == 0} { # Special case for "-exact" range set minList [lreplace $minList end end] if {[compare $vList $minList] == 0} { return 1 } continue } if {[compare $vList $maxList] < 0} { # Within the range => satisfied! return 1 } } return 0 } proc lassign {list args} { foreach v $args {upvar 1 $v x ; set x {}} foreach v $args x $list {upvar 1 $v var ; set var $x} if {[llength $args] < [llength $list]} { set notassigned [lrange $list [llength $args] end] } else { set notassigned {} } return $notassigned } proc {package require} {pkg args} { if {$pkg eq "-exact"} { # Convert legacy syntax (details omitted) } set present [package provide $pkg] if {$present ne ""} { # $pkg already provided; check satisfaction if {[package vsatisfies $present {expand}$args]} { return $present } return -code error "have $present, need $args" } set pass 2 while {$pass} { set acceptable {} foreach v [lsort -command {package vcompare} \ -decreasing [package versions $pkg]] { if {![package vatisfies $v {expand}$args]} { continue } if {[package prefer] eq "latest" || ![string match {*[ab]*} $v]} { # Error handling omitted here uplevel #0 [package ifneeded $pkg $v] return $v } lappend acceptable $v } if {[incr pass -1]} { # use [package unknown] to find more versions } } if {[llength $acceptable]} { # Accept best satisfactory alpha/beta even # though our preference mode is "stable" set v [lindex $acceptable 0] uplevel #0 [package ifneeded $pkg $v] return $v } return -code error "can't find $pkg $args" } # Copyright This document has been placed in the public domain. |
Name change from tip/269.tip to tip/269.md.
|
| < | < | | | | | | | | > | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 269: Add 'string is list' to the 'string is' Subcommand Author: Joe Mistachkin <[email protected]> State: Final Type: Project Vote: Done Created: 19-May-2006 Keywords: Tcl,lists,strings Tcl-Version: 8.5 Post-History: ----- # Abstract The **string** command supports tests for a number of Tcl's basic types, for example, integers, doubles, and booleans. This TIP proposes adding lists to the set of things that can be checked for. # Rationale The **string** command includes tests for the common Tcl types: **string is boolean**, **string is double** and **string is integer**. Unaccountably, **string is list** is missing from the list, making it difficult for an input validation procedure to determine whether, in fact, a string contains a proper list. Currently, something similar to the following incantation is required: set is_list [expr {![catch {llength $str}]}] The above construct \(and others like it\) are extremely counterintuitive, especially to people without intimate knowledge of Tcl. Compare and contrast with: set is_list [string is list $str] Since **string is** currently serves in this capacity for determining whether a string can be correctly interpreted as an integer or double, it seems only natural to extend it so that it can determine whether a string can be correctly interpreted as a list. # Specification This document proposes augmenting the **string is** command with a **string is list** subcommand, as follows: > **string** **is** **list** ?**-strict**? ?**-failindex** _var_? _str_ The result will be **1** if the string has proper list structure; otherwise, it will be **0**. The option **-strict** is accepted for syntactic compatability with other forms of **string is** but has no effect since empty strings are proper lists. # Reference Implementation A reference implementation of this TIP is available <http://sf.net/tracker/?func=detail&aid=1491459&group_id=10894&atid=310894> . # Copyright This document has been placed in the public domain. |
Name change from tip/27.tip to tip/27.md.
|
| < | < | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | < > | < | > | | | | < > | | < | > | | | | | | | | > | 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 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 | # TIP 27: CONST Qualification on Pointers in Tcl API's Author: Kevin Kenny <[email protected]> State: Final Type: Project Vote: Done Created: 25-Feb-2001 Post-History: Discussions-To: news:comp.lang.tcl,mailto:[email protected] Tcl-Version: 8.4 ----- # Abstract Many of the C and C\+\+ interfaces to the Tcl library lack a CONST qualifier on the parameters that accept pointers, even though they do not, in fact, modify the data that the pointers designate. This lack causes a persistent annoyance to C/C\+\+ programmers. Not only is the code needed to work around this problem more verbose than required; it also can lead to compromises in type safety. This TIP proposes that the C interfaces for Tcl be revised so that functions that accept pointers to constant data have type signatures that reflect the fact. The new interfaces will remain backward-compatible with the old, except that a few must be changed to return pointers to CONST data. \(Changes of this magnitude, in the past, have been routine in minor releases; the author of this TIP does not see a compelling reason to wait for Tcl 9.0 to clean up these API's.\) # Rationale When the Tcl library was originally written, the ANSI C standard had yet to be widely accepted, and the _de facto_ standard language did not support a _const_ qualifier. For this reason, none of the older Tcl API's that accept pointers have CONST qualifiers, even when it is known that the objects will not be modified. In interfacing with other systems whose API's were designed after the ANSI C standard, this limitation becomes annoying. Code like: const char* const string = " ... whatever ... "; Tcl_SetStringObj( Tcl_GetObjResult( interp ), (char*) string, /* Have to cast away * const-ness here * even though the string * will only be copied */ -1 ); is more verbose than necessary. It is also unsafe: the cast allows a number of unsafe type conversions \(the author of this TIP has had to debug at least one extension where an integer was cast to a character pointer in this context\). In an C\+\+ environment where engineering practice forbids using C-style cast syntax, the syntax gets even more annoying, although it provides improved safety. C\+\+ code analogous to the above snippet looks like: const char* const string = "...whatever..."; Tcl_SetStringObj( Tcl_GetObjResult( interp ), const_cast< char* >( string ), -1 ); This code is hardly a paragon of readability. The popular Gnu C compiler also has a problem with the _char \*_ declaration of so many of the parameters. With the default set of compilation options, a call like: Tcl_SetStringObj( Tcl_GetObjResult( interp ), "Hello world!", -1 ); results in an error; suppressing this message requires either using the obscure option _-fwritable-strings_ on the compiler command line, or else applying awkward \(and unsafe\) cast syntax: Tcl_SetStringObj( Tcl_GetObjResult( interp ), const_cast< char* >( "Hello, world!" ), -1 ); Introducing CONST on parameters, however, does not bring in any incompatibility; as long as there is a prototype in scope, any ANSI-compliant compiler will implicitly cast non-CONST arguments to be type-compatible with CONST formal parameters. # Specification This TIP proposes that, wherever possible, Tcl API's that accept pointers to constant data have their signatures in _tcl.decls_ and the corresponding source files adjusted to add the CONST qualifier. The change introduces a potential incompatibility in that code compiled on a \(hypothetical\) architecture where pointers to constant data have a different representation from those to non-constant data will not load against the revised stub table. This incompatibility is, in fact, not thought to be a problem, since no known port of Tcl has encountered such an architecture. If we confine the scope of this TIP to adding CONST only to parameters, we preserve complete compatibility with existing implementations. It is neither possible nor desirable, however, to preserve drop-in compatibility across all the API's. The earliest example in the stub table is the _Tcl\_PkgRequireEx_ function. This function is declared to return _char \*_; the pointer it returns, however, is into memory managed by the Tcl library. Any attempt by an extension to scribble on this memory or free it will result in corruption of Tcl's internal data structures; it is therefore safer and more informative to return _CONST char \*_. \(This particular example is also highly unlikely to break any existing extension; the author of this TIP has yet to see one actually use the return value.\) Some of the API's, such as _Tcl\_GetStringFromObj_, will continue to return pointers into writable memory inside the Tcl library. _Tcl\_GetStringFromObj_, for instance, deals with memory that is managed co-operatively between extensions and the Tcl library; one simply must trust extensions to do the right thing \(for instance, not overwrite the string representation of a shared object\). Some of the API's will not be modified, even though they appear to accept constant strings. For instance, _Tcl\_Eval_ modifies its string argument while it is parsing it, even though it restores its initial content when it returns. This behavior has sufficient impact on performance that it is probably not desirable to change it. The cases where the Tcl library does this sort of temporary modification, however, must be documented in the programmers' manual. They affect thread safety and positioning of data in read-only memory. One can foresee that cleaning up the API's that do not suffer from this problem will mean that programmers will be less tempted to use unsafe casts on the ones that remain. Finally, there are a handful of API's that are essentially impossible to clean up portably; the ones that accept variable arguments come to mind. These will be left alone. One particular case in point is _Tcl\_SetResult_: its third argument determines whether its second argument is constant or non-constant. In an environment without writable strings, a call like: Tcl_SetResult( interp, "Hello, world!", TCL_STATIC ); or Tcl_SetResult( interp, "Hello, world!", TCL_VOLATILE ); cannot be handled without unsafe casting. Fortunately, several alternatives are available. The most attractive appears to be: Tcl_SetObjResult( interp, Tcl_NewStringObj( "Hello, world!", -1 ) ); which is also more informative about what is really going on. Note that _TCL\_STATIC_ no longer actually carries the static pointer around. Although _Tcl\_SetResult_ appears to do so, as soon as the command returns, code in _tclExecute.c_ converts the string result into an object result by calling _Tcl\_GetObjResult_. The code using _Tcl\_SetObjResult_ therefore carries no greater performance cost than the original _Tcl\_SetResult_. # Reference Implementation The changes described in this TIP cut across too many functional areas to be implemented effectively all at once. Several people have pointed out that implementing this cleanup all at once appears to be necessary to avoid "CONST pollution," where the library becomes full of code that casts away the CONST qualifier. To study this issue, the author has conducted the experiment of imposing CONST strings on the first API in the stubs table: _Tcl\_PkgProvideEx_. The first concern that arose was that several other functions used the CONST strings passed as parameters, and these functions also needed to be updated. Fortunately, all were static within _tclPkg.c_. Next, when updating the documentation, the author discovered that five other functions were documented in the same man page, and shared a common defintion of the _package_ and _version_ parameters. They, too, were included in the change, and once again, the change was propagated forward into the functions that they called. \(This activity is where the issue of replacing _Tcl\_SetResult_ with _Tcl\_SetObjResult_ was detected.\) When replacing _Tcl\_SetResult_ with _Tcl\_SetObjResult_, the author discovered that the _file_ parameter to _Tcl\_DbNewStringObj_ was also a constant string. With more enthusiasm than caution, he decided to attack the corresponding parameter in all the _TCL\_MEM\_DEBUG_ interfaces. \(In retrospect, it would probably have been easier to tackle this issue separately.\) This change wound up cutting across virtually all of the external interfaces to _tclStringObj.c_ and _tclBinary.c_ and the associated documentation. The author expects that many of the other API's will be much less closely coupled than the one studied. In particular, now that the interfaces of _tclStringObj.c_ have been done once, they don't need to be done again! In fact, starting with the interfaces, like _tclStringObj.c_, that are used pervasively throughout the library and working outward would certainly have been a better course of action than tracing the dependencies forward from one function chosen almost at random. The result of the experimental change was that twenty-eight external APIs, plus about a dozen static functions, needed to have the CONST qualifier added to at least one pointer. After these changes were made, the test suite compiled, linked, and passed all regression tests with all combinations of the NODEBUG and TCL\_MEM\_DEBUG options. It was nowhere necessary to cast away CONST-ness. Possible incompatibility with existing extensions was present only in that the return values from the four functions, _Tcl\_PkgPresent_, _Tcl\_PkgPresentEx_, _Tcl\_PkgRequire_, and _Tcl\_PkgRequireEx_ had the CONST qualifier added. These four functions return pointers to memory that must not be modified nor freed by the caller, so the CONST qualifier is desirable, but existing extensions may depend on storing the pointer in a variable that lacks the qualifier. This level of incompatibility in a minor release has been thought acceptable in the past; changes required to extensions are trivial, and once changed, the extensions continue to back-port cleanly to older releases. An earlier version of these changes was uploaded to the SourceForge patch manager as patch number 404026. The revised version will be added under the same patch number as soon as the author's technical problems with uploading patches are resolved. \(The major difference between the two patches is that the first patch implements the two-Stub approach described under "Rejected alternatives" below. The success of this change has convinced the author of this TIP that the rest of the changes can be implemented in a staged manner, with little source-level incompatibility being introduced for extensions \(and absolutely no incompatibility for stubs-enabled extensions compiled and linked against earlier versions of the library\). # Rejected alternatives The initial version of this TIP attempted to preserve backward compatibility of stubs-enabled extensions, even on a hypothetical architecture where pointer-to-constant and pointer-to-nonconstant have different representations. If this level of backward compatibility is desired, it will be necessary to provide entries in the existing stub table slots corresponding to the API's that lack the CONST qualifiers. The slots in the stub table corresponding to the non-CONST API's can be filled with wrapper functions. For example, the following function definition of _Tcl\_SetStringObj\_NONCONST_ will use the implicit casting inherent in C to call the function with the new API. void Tcl_SetStringObj_NONCONST(Tcl_Obj* obj, /* Object to set */ char* bytes, /* String value to assign */ int length) /* Length of the string */ { Tcl_SetStringObj( obj, bytes, length ); } This sort of definition is so simple that _tools/genStubs.tcl_ was extended in the original patch accompanying this TIP to generate it. For example, the declaration of _Tcl\_SetStringObj_ that once appeared as: declare 65 generic { void Tcl_SetStringObj( Tcl_Obj* objPtr, char* bytes, int length ) } was replaced with: declare 458 -nonconst 65 generic { void Tcl_SetStringObj( Tcl_Obj* objPtr, CONST char* bytes, int length ) } declaring that slot 458 in the stubs table is to be used for the new API accepting a CONST char\* for the string, while slot 65 remains used for the legacy implementation. The difficulty with this approach, which caused it to be rejected, is that it introduces _forward_ incompatibility. Any extension compiled against header files from after the change will fail to load against the stubs table from before the change. This incompatibility would require extension authors to maintain sets of header files for \(at least\) the earliest version of Tcl that they intend to support, rather than always being able to compile against the most current set. This problem was thought to be worse than the hypothetical and possibly non-existent problem of differing pointer representations. # Procedural note The intent of this TIP is that, if approved, it will empower maintainers of individual modules to add _CONST_ to any API where it is appropriate, provided that: * the change does not introduce "CONST poisoning", that is, does not require type casts that remove CONST-ness; * the documentation of the API is updated to reflect the addition of the CONST qualifier; and Individual TIP's detailing the changes to particular APIs shall _not_ be required, provided that the changes comply with these guidelines. # Change history 12 March 2001: Rejected the two-Stubs alternative and reworked the patches to use only one Stub per modified function. # Copyright This document has been placed in the public domain. |
Name change from tip/270.tip to tip/270.md.
|
| < | < | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 270: Utility C Routines for String Formatting Author: Don Porter <[email protected]> State: Final Type: Project Vote: Done Created: 19-Jun-2006 Post-History: Tcl-Version: 8.5 ----- # Abstract This TIP proposes new public C utility routines for the convenience of C-coded extensions and embedded uses of Tcl. # Background During development of Tcl 8.5, several internal routines have been created that provide useful string formatting functions. These routines are most commonly used in the construction of error messages, but have a generally useful nature. The Tcl source code itself makes significant use of them. Making some of these routines public also addresses Feature Request 1184069. # Proposed Changes Add the following routines to Tcl's public interface: ## Tcl\_AppendObjToErrorInfo > void **Tcl\_AppendObjToErrorInfo**\(Tcl\_Interp \*_interp_, Tcl\_Obj \*_objPtr_\) This routine is analogous to the existing routine **Tcl\_AddErrorInfo**, but permits appending a Tcl\_Obj value rather than requiring a **\(const char \*\)**. ## Tcl\_AppendLimitedToObj > void **Tcl\_AppendLimitedToObj**\(Tcl\_Obj \*_objPtr_, const char \*_bytes_, int _length_, int _limit_, const char \*_ellipsis_\) This routine is used to append a string, but to impose a limit on how many bytes are appended. This can be handy when the string to be appended might be very large, but the value being constructed should not be allowed to grow without bound. A common usage is when constructing an error message, where the end result should be kept short enough to be read. Bytes from _bytes_ are appended to _objPtr_, but no more than _limit_ bytes total are to be appended. If the limit prevents all _length_ bytes that are available from being appended, then the appending is done so that the last bytes appended are from the string _ellipsis_. This allows for an indication of the truncation to be left in the string. When _length_ is -1, all bytes up to the first zero byte are appended, subject to the limit. When _ellipsis_ is NULL, the default string **...** is used. When _ellipsis_ is non-NULL, it must point to a zero-byte-terminated string in Tcl's internal UTF encoding. The number of bytes appended can be less than the lesser of _length_ and _limit_ when appending fewer bytes is necessary to append only whole multi-byte characters. The _objPtr_ must be unshared, or the attempt to append to it will panic. ## Tcl\_Format > Tcl\_Obj \* **Tcl\_Format**\(Tcl\_Interp \*_interp_, const char \*_format_, int _objc_, Tcl\_Obj \*const _objv_[]\) This routine is the C-level interface to the engine of Tcl's **format** command. The actual command procedure for **format** is little more than Tcl_Format(interp, Tcl_GetString(objv[1]), objc-2, objv+2); The _objc_ Tcl\_Obj values in _objv_ are formatted into a string according to the conversion specification in _format_ argument, following the documentation for the **format** command. The resulting formatted string is converted to a new Tcl\_Obj with refcount of zero and returned. If some error happens during production of the formatted string, NULL is returned, and an error message is recorded in _interp_, if _interp_ is non-NULL. ## Tcl\_AppendFormatToObj > int **Tcl\_AppendFormatToObj**\(Tcl\_Interp \*_interp_, Tcl\_Obj \*_objPtr_, const char \*_format_, int _objc_, Tcl\_Obj \*const _objv_[]\) This routine is an appending alternative form of **Tcl\_Format**. Its function is equivalent to: Tcl_Obj *newPtr = Tcl_Format(interp, format, objc, objv); if (newPtr == NULL) return TCL_ERROR; Tcl_AppendObjToObj(objPtr, newPtr); return TCL_OK; But it is more convenient and efficient when the appending functionality is needed. The _objPtr_ must be unshared, or the attempt to append to it will panic. ## Tcl\_ObjPrintf > Tcl\_Obj \* **Tcl\_ObjPrintf**\(const char \*_format_, ...\) This routine serves as a replacement for the common sequence: char buf[SOME_SUITABLE_LENGTH]; sprintf(buf, format, ...); Tcl_NewStringObj(buf, -1); Use of the proposed routine is shorter and doesn't require the programmer to determine **SOME\_SUITABLE\_LENGTH**. The formatting is done with the same core formatting engine used by **Tcl\_Format**. This means the set of supported conversion specifiers is that of Tcl's **format** command and not that of _sprintf\(\)_ where the two sets differ. When a conversion specifier passed to **Tcl\_ObjPrintf** includes a precision, the value is taken as a number of bytes, as _sprintf\(\)_ does, and not as a number of characters, as **format** does. This is done on the assumption that C code is more likely to know how many bytes it is passing around than the number of encoded characters those bytes happen to represent. The variable number of arguments passed in should be of the types that would be suitable for passing to _sprintf\(\)_. Note in this example usage, _x_ is of type **long**. long x = 5; Tcl_Obj *objPtr = Tcl_ObjPrintf("Value is %d", x); If the value of _format_ contains internal inconsistencies or invalid specifier formats, the formatted string result produced by **Tcl\_ObjPrintf** will be an error message instead of any attempt to Do What Is Meant. ## Tcl\_AppendPrintfToObj > void **Tcl\_AppendPrintfToObj**\(Tcl\_Obj \*_objPtr_, const char \*_format_, ...\) This routine is an appending alternative form of **Tcl\_ObjPrintf**. Its function is equivalent to: Tcl_AppendObjToObj(objPtr, Tcl_ObjPrintf(format, ...)); But it is more convenient and efficient when the appending functionality is needed. The _objPtr_ must be unshared, or the attempt to append to it will panic. # Compatibility This proposal includes only new features. It is believed that existing scripts and C code that operate without errors will continue to do so. # Reference Implementation The actual code is already complete as internal routines corresponding to the proposed public routines. Implementation is just an exercise in renaming, placing in stub tables, documentation, etc. # Copyright This document has been placed in the public domain. |
Name change from tip/271.tip to tip/271.md.
|
| < | < | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 271: Windows-Style Open and Save File Dialog on Unix Author: Matthew Middleton <[email protected]> Author: susanta kumar mishra <[email protected]> State: Draft Type: Project Vote: Pending Created: 11-Jul-2006 Post-History: Tcl-Version: 8.7 ----- # Abstract This TIP describes updates to the Unix file dialogs to make them more like the dialogs found on the Windows platform. This increases the usability of the dialog for general "power" users. # Rationale It is nice to have a windows-type file dialog for Unix applications that wish to have a Windows appearance. This makes the experience much smoother for end-users that are experienced with the Windows file dialogs, which is an extremely common case these days. It has convienent attributes of being able to reorder file lists by name, type, size, and date. It also has the typical cut, copy, paste, rename, delete, new directory and properties selections. Box selecting is also possible with the multiple option. As much functionality as possible was included to match the windows dialog. Some things were left out, such as the panel at the left of a typical windows dialog that contains buttons that allow quick change to such things as "My Documents, and "My Computer". # Reference Implementation The source code has been included as script files. All of this was done at the Tcl script level, and can be found in Patch 1520742 \(currently written against Tcl/Tk 8.4.12\). <http://sf.net/tracker/?func=detail&aid=1520742&group_id=12997&atid=312997> Listing of modified/new files: tkfbox.tcl choosedir.tcl tkfprops.tcl Tkfprops.html ResizeButs.tcl ResizeButs.html Two new megawidgets have been developed for these changes. They are **ResizeButs** which is a button-alike specialized for acting as the heading of a column or row of data, and **tk\_fileProperties_ which is a popup window for viewing and editing file metadata. # Specification The **tk\_getOpenFile** and **tk\_getSaveFile** have been greatly improved to function much like a Windows file dialog \(circa Windows 2000\), when the default dialogs are overridden. This is most useful on Unix systems where the application is wanted to have a Windows-like appearance, but it will also function on Windows. I have not been able to test on Macintosh. This also affects **tk\_chooseDirectory** when the default dialogs are overridden, as that is also implemented in _tkfbox.tcl_. The dialogs will work without the BWidget package, but it will have more functionality and look more like a windows dialog if BWidgets are available. The only thing it really needs from BWidgets is the **ComboBox** widget. If this were included in regular Tk, then BWidgets would not be needed. It also uses the balloon messages of the "Button" widget from BWidgets. This new file dialog widget requires two of the new widgets included - **ResizeButs** and **tk\_fileProperties**, which are autoloaded from _ResizeButs.tcl_ and _tkfprops.tcl_ respectively. The two tcl files that define these widgets are included, along with documentation on each one. The file _choosedir.tcl_ is also included. It is needed to work with the modified _tkfbox.tcl_. ## Functionality Outline Added functionality of the file dialog: 1. Back directory button 2. Create directory button 3. Details button 4. Delete button 5. You can type the directory path at the top \(requires BWidgets\). Selecting "desktop" expands what's available on the desktop if used on Windows. > Right mouse clicking on a file gives these options: > 1. Cut > 2. Copy > 3. Delete > 4. Rename > 5. Properties \(uses tk\_fileProperties widget\) > Right mouse clicking in open white space gives these options: > 1. View > 1. List > 2. Details > 2. Arrange Icons > > 1. By Name > > 2. By Size > > 3. By Type > > 4. By Date > 3. Refresh > 4. Paste \(ungreys if Cut or Copy were previously selected on files\) > 5. New Folder > 6. Properties \(uses tk\_fileProperties widget\) 6. Recent selected files can be shown by pressing the down arrow in the entry field of the selected file name \(requires BWidgets\). Recent file names are saved to a file named .tk\_recent\_selections in the users home directory. 7. Box selecting of files can be done with the "multiple 1" option. Left mouse click and hold and drag a box over files. 8. The busy was improved to actually block mouse clicks instead of just showing an hourglass widget. 9. Popup button descriptions. \(requires BWidgets\) 10. Icons shade as well as text when selected. ## Details View The Details button grids 4 columns \(name, file type, size, and modified date\). \(This uses ResizeButs widget.\) Moving the mouse over the border between two buttons of the top column headings and left mouse clicking while dragging will allow the user to change the size of the columns. Pressing one of the heading buttons changes the order of the data between increasing and decreasing and displays a triangle in the button to indicate the order. ## Additional Arguments to the tk\_getOpenFile and tk\_getSaveFile Commands The _dir\_leaf_ arguments allow a folder to be selected as a file to select it as a project. Providing a **-dir\_leaf\_check** procedure defines the file dialog as a special type that only lists folders, but the folder that passes the **-dir\_leaf\_check** procedure can be selected as a file. 1. **-dir\_leaf\_check** _commandName_ - This is the name of a procedure which checks if the directory qualifies as the kind that can be selected as a project file. It returns a non-zero number if it qualifies, otherwise it returns zero. The directory name to check will be appended as an argument to the procedure. 2. **-dir\_leaf\_image** _imageName_ - an image to use for the folder types that will be treated as files. It should be an image created with **image create photo**. 3. **-dir\_leaf\_label** _string_ - text that appears at the left of the entry for the selected file when the dialog is defined as a project folder selection type \(when the **-dir\_leaf\_check** procedure is defined\). Not localized by Tk. 4. **-extra\_widgets\_bottom** _commandName_ - This is the name of a procedure which packs or grids additional widgets at the bottom of the dialog. The window name of a frame widget at the bottom of the dialog is appended as an argument, and any further widgets that this procedure creates to be gridded should be a child window of this frame. If this procedure returns anything, it will be treated as a number to configrue the width of the Ok and Cancel buttons, since the additional widgets could possibly stretch these buttons to any length. 5. **-extra\_widgets\_side** _commandName_ - This is the name of a procedure which does the packing or gridding for additional widgets at the right side of the dialog. The frame window name at the right side of the dialog will be appended as an argument. 6. **-pick\_func** _commandName_ - A procedure which will be done every time a file is selected \(activated\). The full path of the file name will be appended as an argument to this procedure. 7. **-allow\_nonexistent** - If the command used is **tk\_getOpenFile**, this will allow the user to enter a nonexistent file name. This name will be returned from **tk\_getOpenFile**, but it will still not exist. It is the programmer's responsibility to create this file afterwards. 8. **-open\_button\_name** _string_ - Alternate text to use for the "Open" or "Save" button. Not localized by Tk. # Copyright This document has been placed in the public domain. |
Name change from tip/272.tip to tip/272.md.
|
| < | | | | | | < | | | > | | | | | | | | | | | | | | | | > | 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 | # TIP 272: String and List Reversal Operations State: Final Type: Project Tcl-Version: 8.5 Vote: Done Post-History: Author: Donal K. Fellows <[email protected]> Created: 23-Aug-2006 Keywords: Tcl, lreverse ----- # Abstract This TIP proposes adding commands to reverse the order of characters in strings and elements in lists. # Rationale According to a recent thread on news:comp.lang.tcl <http://groups.google.com/group/comp.lang.tcl/browse_frm/thread/a0b8c98c00a31ffc> , there are a number of use cases for reversing strings and lists. While it has always been possible to write Tcl code to do this, it has typically been a fairly inefficient operation, and for some algorithms \(admittedly including ones that are benchmarked when comparing Tcl to other languages\) this can be the source of a painful slowdown. By putting an efficient implementation in the Tcl core, we will speed up quite a bit of code, more than I originally anticipated it seems; this will make us look better to programmers without much experience with the language too. # Proposed Change I propose to add two commands, **lreverse** to reverse the order of items in a list, and **string reverse** \(a subcommand of **string**\) to reverse the order of characters in a string. I do not propose to provide any C-level API for performing these operations. ## The lreverse Command This shall have the following syntax: > **lreverse** _list_ It shall return a list that is the same as the input list but with the elements in reverse order. ## The reverse Subcommand of the string Command This shall have the following syntax: > **string reverse** _string_ It shall return a string that is the same as the input string but with the characters in reverse order. \(Note that it shall also return a byte array when the input is a byte array.\) # Copyright This document has been placed in the public domain. |
Name change from tip/273.tip to tip/273.md.
|
| < | < | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 273: Add Tcl_Expr... Support to Tcl_Get... Functions Author: Carsten Gosvig <[email protected]> State: Rejected Type: Project Vote: Done Created: 30-Aug-2006 Post-History: Tcl-Version: 8.5 Obsoletes: 176 ----- # Abstract This TIP proposes adding **Tcl\_Expr**... calls to **Tcl\_Get**... functions, supporting direct use of expressions for arguments to commands that is defined as int, long, wide-int, double or boolean. # Rationale Many of Tcl's commands takes an int, long, wide-int, double or boolean as an argument. For list and string commands even in the format of **end-**_N_. However, this is limited to a direct string conversion of the argument to one of the mentioned types, so for even simple expression the **expr** command has to be called explicitly, which is quite cumbersome as can be seen in the following examples: set x [lsearch $list $elem] set new [lrange $list [expr $x-1] [expr $x+1]] set x [string first $string "foo"] set new [string range $string $x [expr [$x+5]] set x [lsearch $list $elem] set hex [format "%X" [expr {$x & 0xFF}]] set file [open $name] set buf [read $file [expr {$len * 2 - 10}]] incr var [expr $step*5+1] after [expr $sec*1000] # Specification By adding a call to a **Tcl\_Expr**... function at the point where the current conversion fails in the **Tcl\_Get**... functions \(at the label named _bad_ in the current implementation\) we will add support for using expressions directly as arguments without needing to go through the **expr** command: set x [lsearch $list $elem] set new [lrange $list $x-1 $x+1] set x [string first $string "foo"] set new [string range $string $x $x+5] set x [lsearch $list $elem] set hex [format "%X" {$x & 0xFF}] set file [open $name] set buf [read $file {$len * 2 - 10}] incr var $step*5+1 after $sec*1000 This TIP does not propose any alterations to any function or procedure signatures. ## Implementation Notes The **Tcl\_Get**<_Type_> functions needs to be updated with a call to the **Tcl\_Expr**<_Type_> functions, and the **Tcl\_Get**<_Type_>**FromObj** functions need to be updated with a call to the **Tcl\_Expr**<_Type_>**Obj** functions. ## Compatibility There should be no compability issues, as this TIP only adds functionality to a current error situation. This proposal renders [[176]](176.md) obsolete, as that describes a solution that is effectively a subset of this TIP. # Copyright This document has been placed in the public domain. |
Name change from tip/274.tip to tip/274.md.
|
| < | < | | | | | | | | | | | | > | | | | | | | | | | | | | | | | > | 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 | # TIP 274: Right-Associativity for the Exponentiation Operator Author: Arjen Markus <[email protected]> Author: David Smith <[email protected]> Author: Richard Suchenwirth <[email protected]> Author: Don Porter <[email protected]> Author: Sérgio Loureiro <[email protected]> State: Final Type: Project Vote: Done Created: 15-Sep-2006 Post-History: Keywords: Tcl,expr Tcl-Version: 8.5 ----- # Abstract This TIP clarifies and corrects the associativity behaviour of the exponentation operator that was introduced in [[123]](123.md). # Background The exponentiation operator found in various programming languages has a distinct right associativity. In this way it differs from the other arithmetic operators. Some languages do implement with left-associativity but this is felt to be awkward by many users. [[123]](123.md) introduced an exponentiation operator into Tcl 8.5 and was quite elaborate in defining its behaviour with respect to integer arguments, as there are quite a few corner cases to be examined. However, it was vague on the issue of associativity and in fact showed by one example that the operator as implemented then was left-associative. # Rationale A left-associative exponentiation operator is less useful than a right-associative operator, as pointed out in the Wikipedia article <http://en.wikipedia.org/wiki/Associative> . To illustrate, a left-associative exponentiation operator behaves like this: > _x_ **\*\*** _y_ **\*\*** _z_ = \(_x_ **\*\*** _y_\) **\*\*** _z_ = _x_ **\*\*** \(_y_ \* _z_\) Whereas a right-associative exponentiation operator behaves like this: > _x_ **\*\*** _y_ **\*\*** _z_ = _x_ **\*\*** \(_y_ **\*\*** _z_\) Thus, if the operator is left-associative, then the above expression can be rewritten using a single exponentiation. For this reason many programming languages and mathematical systems, among these Fortran, Perl, Python, Scilab, Mathematica and Maple, have chosen right-associativity. Several others, MATLAB and Octave, which is intended to be compatible to MATLAB, use left-associativity. \(Microsoft Excel also uses left-associativity, but this product exhibits more quirky arithmetic behaviour and therefore should not be considered as a serious factor, in at least one author's opinion.\) # Proposal Therefore, given the expectation of programmers, the choice made in many programming languages and mathematical systems and the arguments about the limited usefulness of left-associativity, this TIP proposes to correct the behaviour of the exponentiation operator. It should be right-associative, so that: 2 ** 3 ** 4 = 2 ** (3 ** 4) = 2 ** 81 = 2417851639229258349412352 \(and not 4096, if left-associativity is used\) # Compatibility No official version of Tcl 8.5 has been released yet. Existing "private" extensions that define an exponentiation operator that we are aware of use the right-associativity as well. Therefore this correction will only enhance compatibility. # Copyright This document is placed in the public domain |
Name change from tip/275.tip to tip/275.md.
|
| < | < | | | | | | | | > | | | | | | | | | | | | | | | > | 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 | # TIP 275: Support Unsigned Values in binary Command Author: Pat Thoyts <[email protected]> State: Final Type: Project Vote: Done Created: 27-Sep-2006 Post-History: Keywords: Tcl,binary,unsigned Tcl-Version: 8.5 ----- # Abstract This TIP proposes to add support for unsigned values to the **binary** command. # Rationale It is quite common when handling binary data to need to read unsigned values. All values read in by **binary scan** are converted to integers and sign extended, which requires code to trim the excess bits using the **expr** command if the values need to be treated as unsigned values. This makes Tcl slow when handling large quantities of binary data, for instance in crytographic or checksum functions. Simply by avoiding this **expr** operation we significantly improve the speed of processing such data. # Specification The **binary scan** should be updated so as to add a flag identifier into the binary field format. This makes the field specification: > <_type code_><_flag_>?<_length_>? The flag character for unsigned fields \(the only one defined\) is "u", so the following are all acceptable: cu\*: read all bytes as unsigned c2cu2: two signed bytes then two unsigned bytes su2: two unsigned little-endian shorts Su: a single big-endian unsigned short. iu: a single unsigned little-endian integer mu3: three unsigned machine-endian 64-bit integers. The "u" flag will be supported combined with all field types but will have no effect on non-integer types. Also the flag is valid but ignored for the **binary format** command. # Reference Implementation A reference implementation is available in SourceForge Patch 156751 <http://sf.net/tracker/?func=detail&aid=1565751&group_id=10894&atid=310894> . # Copyright This document is placed in the public domain. |
Name change from tip/276.tip to tip/276.md.
|
| < | < | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 276: Specify and Unify Variable Linking Commands Author: Miguel Sofer <[email protected]> State: Draft Type: Project Vote: Pending Created: 01-Oct-2006 Post-History: Keywords: Tcl,global,variable,upvar,namespace upvar Tcl-Version: 8.7 ----- # Abstract The purpose of this TIP is to simplify and clarify the semantics of the commands in Tcl that couple variables in different scopes together. # Rationale This TIP proposes to specify and document the behaviour of the different variable linking commands in Tcl: **global**, **variable**, **upvar** and **namespace upvar**. In particular, as many of these commands were initially designed to be mainly useful from within procedure bodies, the documentation does not specify their behaviour with respect to qualified variable names. This TIP proposes to specify and document this behaviour, insuring that it is essentially the same in all these commands. ## Current Situation There have been a few bug reports concerning the behaviour of variable linking commands with respect to qualified variable names: 604226, 1274916, 1274918. Some are real bugs, some are just surprising but correct behaviour, some are surprising unspecified behaviour. Within proc bodies all of these commands create local variables that are linked to original variables elsewhere \(the following assumes that _local_ is a non-qualified name\): * "**global** _var_" creates a local variable "[**namespace tail** _var_]" that is linked to "_var_" as resolved from the global namespace. * "**variable** _var_" creates a local variable "[**namespace tail** _var_]" that is linked to "_var_" as resolved from [**namespace current**]. * "**upvar** _level var local_" creates a local variable "_local_" that is linked to "_var_" as resolved in the context of the frame identified by _level_. It is an error to try to link to a proc-local variable from a namespace context. It is an error to link a variable to itself. * "**namespace upvar** _ns var local_" creates a local variable "_local_" that is linked to "_var_" as resolved from namespace _ns_ \(itself resolved in the current context\). It is an error to link a variable to itself. One undocumented issue is what should happen when _local_ is a qualified name. Another issue is the behaviour of these commands when invoked outside of procedure bodies: * "**global** _var_" is documented to be a no-op. * "**variable** _var_" is documented to create a namespace variable in the current namespace, without any mention of the behaviour when "_var_" is qualified. Currently that is a a no-op in terms of creating a variable, but it can change the value of the target, see [Bug #604226]. If **var** is a simple name and the corresponding variable already existed, **variable** may set its value \(and an internal flag\), but does no linking. * "**upvar** _level var local_" creates a variable "_local_" \(as resolved from [**namespace current**]\) that is linked to "_var_" as resolved in the context of the frame identified by _level_. It is an error to try to link to a proc-local variable from a namespace context. It is an error to link a variable to itself. * "**namespace upvar** _ns var local_ creates a variable "_local_" \(as resolved from [**namespace current**]\) that is linked to "_var_" as resolved from namespace _ns_ \(itself resolved in the current context\). It is an error to link a variable to itself. # Proposal This TIP proposes to unify the criteria, making all of these commands essentially implementable in Tcl from the most general, **upvar**. The behaviour should _not_ depend on the commands being invoked within or outside of a procedure body. In all of the following, it is an error for _local_ to be a qualified variable name. * "**global** _var_" always creates a variable "[**namespace tail** _var_]" in the current context, linked to a global variable "_var_". * "**variable** _var_" always creates a variable "[**namespace tail** _var_]" in the current context, linked to a variable "_var_" as resolved from [**namespace current**]. * "**upvar** _level var local_" always creates a variable "_local_" in the current context, linked to "_var_" as resolved in the context of the frame identified by _level_. It is an error to try to link to a proc-local variable from a namespace context. * "**namespace upvar** _ns var local_" always creates a variable "_local_" in the current context, linked to "_var_" as resolved from namespace _ns_ \(itself resolved in the current context\). In all cases, attempting to link a variable to itself will be a no-op. # Compatibility This TIP may cause breakage in some scripts relying on undocumented behaviour. The specification changes for **global** and **variable** outside of proc bodies is almost certainly implementing what the programmer meant them to do, hence likely to fix more bugs than it causes. # Reference Implementation and Documentation Forthcoming at SF. # Copyright This document has been placed in the public domain. |
Name change from tip/277.tip to tip/277.md.
|
| < | < | | | | | | | > | | | | | | | | | | | | < > | | | | | | > | 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 | # TIP 277: Create Namespaces as Needed Author: Miguel Sofer <[email protected]> State: Draft Type: Project Tcl-Version: 8.7 Vote: Pending Created: 01-Oct-2006 Post-History: ----- # Abstract This TIP proposes that namespaces be created automatically whenever a script tries to create a command, variable or child namespace in it. # Proposal As proposed in [FR 582926], whenever a script tries to create a command, variable or namespace, Tcl should automatically create all namespaces in the path if they do not already exist. In other words, as an example, the current behaviour % namespace children [namespace current] ::activestate ::tcl % set a::b::x 2 can't set "a::b::x": parent namespace doesn't exist % namespace children [namespace current] ::activestate ::tcl should become % namespace children [namespace current] ::activestate ::tcl % set a::b::x 2 2 % namespace children [namespace current] ::a ::activestate ::tcl % namespace children ::a ::a::b # Reference Implementation and Documentation Forthcoming at SF. # Copyright This document has been placed in the public domain. |
Name change from tip/278.tip to tip/278.md.
|
| < | < | | | | | | | | | | > | | | | | | | | | | | | | | | | | < > | | < > | < > | | | | | | < > | < > | | | | < > | < > | | | | | | | < > | < > | | | | | < > | < > | < > | | | | | < | > | | | | | | | | | < > | | | | | | | | | | | | | | | | | | < > | | | | | | | | > | 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 | # TIP 278: Fix Variable Name Resolution Quirks Author: Miguel Sofer <[email protected]> Author: Miguel Sofer <[email protected]> Author: Kevin Kenny <[email protected]> Author: Jan Nijtmans <[email protected]> State: Draft Type: Project Vote: Pending Created: 03-Oct-2006 Post-History: Tcl-Version: 9.0 ----- # Abstract This TIP proposes to fix the behaviour for variable name resolution, modelling it on the resolution for namespace names instead of the current command name resolution. # Definitions * a variable name is "simple" if it does not contain the character sequence "::". * a variable name is "absolute" if it starts with the character sequence "::". * a variable name is "relative" if it is neither simple nor absolute, it contains the character sequence "::", but not at its beginning. # Specification Variable name resolution shall proceed as follows: * a simple name refers to a local variable if within a proc body, to a variable resolved [*] in the current namespace otherwise * an absolute name does not need resolving, ::foo::bar::baz always refers to a variable named "baz" in a namespace named "bar" that is a child of a namespace named "foo" that is a child of the global namespace of the interpreter [*]. * a relative name is always resolved [*] starting at the current namespace. In the absence of special resolvers, foo::bar::baz refers to a variable named "baz" in a namespace named "bar" that is a child of a namespace named "foo" that is a child of the current namespace of the interpreter. The changes with respect to the current behaviour is for relative names in all contexts, and simple names outside of proc bodies: the alternative lookup starting from the global namespace is lost. The resolution is independent of the previous existence of namespaces or variables. The 'declaration' of namespace variables with the **variable** command, currently needed to avoid some confusing behaviour, becomes unnecessary. In short: > **It is possible to know what variable is meant by just looking at its name and knowing the context, without any interference from the rest of the program.** These are the same rules as presently used for the resolution of namespace names. [*] Currently there are hooks in the core for special resolvers that can be attached to a namespace or interpreter, mainly \(only?\) used by itcl. The present TIP does not address resolvers, except for the specification that an absolute name ignores them. The rule that a simple name in a proc-body always refers to a local variable is not new in that sense, as any resolver hooks in that case create local variables linked to some other vars, in the manner of upvar. # Rationale: avoid confusion Repeating myself: the rationale is to make it a reality that > **It is possible to know what variable is meant by just looking at its name and knowing the context, without any interference from the rest of the program.** Ever since the birth of namespaces, the resolution path for variables has been modelled on the resolution path for commands: if a variable is not found in the current namespace, it will be looked up in the global namespace. This behaviour hides a few surprises, especially but not only with respect to creative writing. Consider for instance the test test namespace-17.7 {Tcl_FindNamespaceVar, relative name found} { namespace eval test_ns_1 { unset x set x ;# must be global x now } } {314159} as well as following examples: % set x 1 1 % namespace eval a set x 1 % set a::x can't read "a::x": no such variable % namespace eval b {upvar #0 x y} % info vars x % namespace eval a set x 1 1 % set x 1 % namespace eval a set x can't read "x": no such variable % set x 1 1 % namespace eval a set x 1 % upvar 0 ::a::x y % namespace eval a set x can't read "x": no such variable % namespace eval a set x can't read "x": no such variable % set x 1 1 % namespace eval a set x 1 % trace add variable a::x read {;#} % namespace eval a set x can't read "x": no such variable % set x 1 1 % namespace eval a {set x 2; set y 3} 3 % set x 2 % info vars a::* ::a::y % set a::x can't read "a::x": no such variable % set a::y 3 In order to restore some sanity, **variable** has been invented to selectively force the behaviour that this TIP is proposing \(in its usage outside of procedure bodies\). The present behaviour forces a subtle and confusing concept of "variable existence", forcing some implementation details to be visible to scripts. Internally, a variable may * not exist at all * exist in the namespace's hash table, but be undefined * exist and have a value In principle scripts should not be able to distinguish the first two states - except as to the existence of traces on undefined variables. In particular, the existence of a link to an undefined variable \(which forces the target to exist in state 2\) should have no influence whatsoever on the concept of variable existence. But it does \(see examples in \#959052\). This behaviour also causes [namespace which -variable] and [info vars] to give different answers as to the existence of variables: the first looks in the hashtable, the second verifies that the variable has a value or that it has been declared via [variable]. Some of the problems inherent in the current way of things are illustrated by Bugs 959052, 1251123, 1274916, 1274918, 1280497 Bug 1185933 is perhaps particularly illustrative. In it, Kevin Kenny <[email protected]>, a long-time Tcl maintainer \(and reputed expert\) had placed in 'clock.tcl' the group of lines: set i 0 foreach j $DaysInRomanMonthInLeapYear { lappend DaysInPriorMonthsInLeapYear [incr i $j] } unset i j within a [namespace eval] context. This code performed without ill effect for some months, until it was observed that it would cause a failure if a script were to create a variable named 'i' or 'j' in the global context prior to the first invocation of the [clock] command. This case was also inordinately difficult to simulate in the test suite, because tcltest reads the clock as part of its initialization. The fix was to move the offending code from the [namespace eval] into an 'init' procedure \(which was called once and then deleted via [rename]\). # Side Benefit: Code Simplification, Performance Variable name resolution has a relatively complicated implementation, and interplays strangely with many core commands - in particular **variable** and **upvar**. This TIP would enable a non-negligible simplification of a lot of code. An optimisation in variable name caching that permits massive speed improvements in namespace variable accesses could also be enabled - it is currently \#ifdef'ed out, it was active briefly in Tcl8.5a2. Note that currently it is wrong to cache the pointer to an undefined variable: as the variable has to be kept in the corresponding hashtable, the variable jumps from the first to the second state of inexistence. This may cause breakage in scripts depending on full non-existence. See also Bug 959052. Quite a few flag values that are currently needed to specify special code behaviour under different circumstances \(VAR\_NAMESPACE\_VAR, LOOKUP\_FOR\_UPVAR, possibly others\) become obsolete: the behaviour is the same under all circumstances. # Down-Sides This is known to expose some "bugs" in code in the wild, and break at least one program \(AlphaTk, see below\). ## AlphaTk breakage AlphaTk breaks with this change <http://aspn.activestate.com/ASPN/Mail/Message/Tcl-core/2083396> <http://sf.net/tracker/?func=detail&aid=959786&group_id=10894&atid=110894> . This is the result of code of the form namespace eval foo {} proc foo::bar {} { global foo::name set foo::name 1 } which works since Tcl7.x until now, and would cease to work properly if this change is implemented. It is interesting to understand how this code works: * **Tcl7.x** I assume that there is conditional compat code that makes **namespace** a noop. The code creates a global variable foo::name, the proc accesses it as required by **global**. * **Tcl8.x** the code links the local variable "name" to the global "::foo::name"; after this, "name" goes unused. The access to the variable is by the name "foo::name": first "::foo::foo::name" is attempted, and, as it does not exist, "::foo::name". As this variable exists, in the sense that it is in the global hashtable by virtue of the created link, it is used. Note that the code works in Tcl8.x through a quirk, and that it foregoes the usage of fast local variable access to "name". Should this TIP be accepted, I commit to helping out with the adaptation of AlphaTk. Note also that, should both this TIP and [[277]](277.md) be accepted, the code will continue to work as is through a different quirk. In that case, the namespace "::foo::foo" would be created, and the variable "::foo::foo::name" would be getting all the action. The code is however fragile, this aspect is not to be understood as minimising the impact of this TIP. # Reference Implementation and Documentation A cvs branch tip-278-branch has been opened to test the implementation of this tip; the modifications are logged in the Changelog of the branch. # Notes * **namespace which -variable var** becomes relatively useless, as it will always return either \{\} or [namespace current]::var whenever var is not fully qualified. * the only effect of **variable** outside of proc bodies is now on **namespace which -variable var**. This might change again if TIP276 is approved # Copyright This document has been placed in the public domain. |
Name change from tip/279.tip to tip/279.md.
|
| < | < | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 | # TIP 279: Adding an Extensible Object System to the Core Author: Gustaf Neumann <[email protected]> Author: Larry W. Virden <[email protected]> State: Draft Type: Project Vote: Pending Created: 05-Oct-2006 Post-History: Tcl-Version: 8.7 ----- # Abstract This TIP proposes adding OO support to the Tcl core, consisting mostly of a dispatcher plus a small number of helper commands. The TIP allows the coexistence of multiple object systems by providing a common framework, the Tcl Minimal Object System \(TMOS\). The framework will contain, as well, a small, basic oriented language \(Tcl Core Object Oriented Language, TclCOOL\) to make it usable in the core without any extensions. All defined commands of the minimal object system are defined in the **::oo** namespace, which is not used by any current mainstream OO system. It has been designed specifically to allow a relatively simple re-implementation of the known object systems. # Rationale and Basic Requirements Rather than proposing any kind of OO language, the TIP suggests to add a framework to the core that many existing and future extensions \(including XOTcl\) can use. This framework alone is not useful as an OO language, but is an environment that can host multiple OO languages in parallel, such as Snit or XOTcl \(maybe the language from current [[257]](257.md) as well\), without pushing a single model. Languages like Snit or XOTcl can continue to develop, the core developers can optimize and integrate better with the tcl-core, etc. The framework \(Tcl Minimal Object System, TMOS\) consists of an flexible object interpreter \(dispatcher\) able to run the most powerful current object extensions. This dispatcher is accompanied by a "minimal object system" and a small set of predefined, but unattached methods \(basic method set\) and an "extension mechanism". For the bootstrapping of different object systems, only a single method for allocating objects or classes is proposed, plus a few commands for setting up the object/class relations and registering methods. The Tcl Minimal Object System is used for the definition of TclCOOL \(Tcl Core Object Oriented Language\). TclCOOL is simple but powerful object language realized with TMOS. Additional object systems \(like XOTcl, SNIT or STOOP\) can be loaded as an extensions \(being not part of the core\), and can provide their own method-sets \(or re-use the predefined method set, or reuse the methods-set of some extension\). This approach provides a flexibility much higher than in other popular scripting languages and lets object system designers continue to improve their work based on Tcl. # The Tcl Minimal Object System The minimal object system consists of a base class \(**::oo::object**\) and a meta-class \(**::oo::class**, subclass of **::oo::object**\). name of class kind of class superclass instance-of ========================================================== ::oo::object class ::oo::object ::oo::class ::oo::class meta-class ::oo::object ::oo::class The meta-class **::oo::class** has two methods named "**alloc**" and "**dealloc**" \(names are arbitrary, as shown later\) to create objects or classes. **::oo::object** has no methods at all. The minimal object system is intended to be specialized by one or more different object systems. An object system is created by sub-classing the base classes, configuring these according to the object systems needs. This configuration consists of defining its relations to the general base and meta-class, and equipping these extension-specific classes with additional functionality \(providing methods\). The whole configuration of the object system can be done completely from the scripting level. The minimal object system defines the following commands and methods in the ::oo namespace: * Two classes ::oo::class ::oo::object * Two unexported Tcl commands for OO-language designer ::oo::alias ::oo::setrelation * Three exported Tcl commands to be used by in the languages ::oo::my ::oo::self ::oo::next * An unregistered \(unattached\) set of methods that can be used for classes alloc, dealloc, instproc, instforward, info * An unregistered \(unattached\) set of methods that can be used for objects instvar forward info The Tcl command ::oo::setrelation ::oo::setrelation class|obj <relation> <target> allows one to define/redefine relations between objects, classes and mixins. This is a primitive command designed for the language developer, not for the user of the implemented object oriented language. The following relations are supported: **mixin** \(abbreviation for per-object mixin\), **instmixin** \(for per-class mixin\), **filter** \(for per-object filter\), **instfilter** \(for per-class filter\), **class**, and **superclass**. The meaning of these relations is defined by the dispatcher, which is responsible for the linearization of the commands. The dispatcher determines the invocation order depending on the precedence order and the resolution order. The precedence order defines the priorization of classes and determines therefore the shadowing of methods. The precedence order is per-object mixins, followed by per-class mixins, followed by the class hierarchy. All of these refer not to single classes but to class hierarchies, where the contained classes are linearized; when a class is mixed into a precedence order, where it is already present, it has no effect. The precedence of object specific methods is between mixins and the intrinsic class hierarchy. The method resolution order overlays the precedence order. While the precedence order determines, what method should be called, the method resolution order determines what other methods should be called before this method. The resolution order supports per class filters \(methods to be called before every method dispatch for every instance of this class\) and per-object filters \(to be called before every method dispatch of this object\). Filters are defined in a filter chain, where object specific filters take precedence over class specific filters. Filters can change the results of methods. Immediately before and after certain methods pre- and post-conditions can be evaluated \(similar to method-combinators in CLOS\), between statements, invariants can be checked. The invocation order defines the layering of methods, the method chaining \(calling shadowed/filtered methods\) is performed through the command next. Per-object filters, per-class filters, per-object mixins and per-class mixins can be applied conditionally based on tcl-expressions \(guards\) executed int the object context. When an undefined method is invoked on an object, the call \(method name and the arguments of the invocation\) are passed to the method **unknown**. If no such method exists, an error message is generated. The Tcl command ::oo::alias ::oo::alias class|obj methodName ?-objscope? ?-per-object? cmdName registers a command \(_cmdName_\) under a certain name \(_methodName_\) to an object or class \(1st argument\) to make the command available as a method. The options _-objscope_ makes instance variables of the object/class appear as local variables, therefore Tcl commands to which variable names are passed \(e.g. set, append, lappend, ...\) can access instance variables without additional effort. ## Example for defining TclCOOL \(Tcl Core Object Oriented Language\) ### Create base and meta class: namespace eval tcl-cool {} ::oo::class alloc ::tcl-cool::object ::oo::class alloc ::tcl-cool::class After creation, the classes ::tcl-cool::class and ::tcl-cool::object are instances of ::oo::class. This is not what we want to have. _tcl-cool::object_ should be the most general superclass of TclCOOL, and _tcl-cool::class_ should be the most general superclass of TclCOOL. Without this redefinition ::tcl-cool::class and ::tcl-cool::object would not have methods \(except alloc and dealloc\), even if we provide methods for these base classes. ### Define the basic class relations: Since we are bootstrapping the language from a minimal command-set, we will use the setrelation command to define the basic relationships of the freshly defined classes. First, we define that the superclasses of the newly defined class named _::tcl-cool::class_\) should be the general meta-class ::oo::class and as well _::tcl-cool::object_. Therefore, ::tcl-cool::class will be a meta-class \(its instances are classes\) and it will inherit all properties of the most general TclCOOL class. ::oo::setrelation ::tcl::cool::class superclass {::oo::class ::tcl-cool::object} The next two commands define that ::tcl-cool::object and ::tcl-cool::class are instances of ::tcl-cool::class. In other words, the class of e.g. ::tcl-cool::object is ::tcl-cool::class. ::oo::setrelation ::tcl-cool::object class ::tcl-cool::class ::oo::setrelation ::tcl-cool::class class ::tcl-cool::class The basic OO-relations of the two basic classes are defined. In a next step of the bootstrapping we attach methods to these classes. ### Define methods for classes: We define 3 methods for _::tcl-cool::class_ based on the method-set for classes: * _method_ is a means to define the methods, which are provided to the instances of the class \(_instproc_ in XOTcl\) * _forward_ is a forwarder for instances of the object \(_instforward_ in XOTcl\) * _info_ is an introspection method for classes ::oo::alias ::tcl-cool::class method ::oo::methodset::class::instproc ::oo::alias ::tcl-cool::class forward ::oo::methodset::class::instforward ::oo::alias ::tcl-cool::class info ::oo::methodset::class::info ### Define methods for objects: Next, we define 3 methods for _object_ \(actually _::tcl-cool::object_\) based on the method-set for objects: * _variable_ is a means to import instance variables into the current scope \(_instvar_ in XOTcl\) * _forward_ is a method for delegating calls to different objects * _info_ is an introspection method for objects ::oo::alias ::tcl-cool::object variable ::oo::methodset::object::instvar ::oo::alias ::tcl-cool::object forward ::oo::methodset::object::forward ::oo::alias ::tcl-cool::object info ::oo::methodset::object::info The full definition of TclCOOL is available from <http://media.wu-wien.ac.at/download/tcl-cool.tcl> # Methods from Extensions This proposal defines only a small method-set \(see above\). However, it makes it straightforward to reuse the existing method-set \(with maybe different names\) without forcing an intermediate interpretation layer, or to load an additional method-set as extension. This additional method-set can be loaded dynamically via **package require**. The object system developer can provided the methods as Tcl commands in the extension's namespace. These commands can be attached to the objects and classes of the object system to be defined with the command _::oo::alias_. The command alias should not allow extensions to register methods on **::oo::object** and **::oo::class**. All application object systems should only be allowed to register their methods on the language specific superclasses. The exact API for methods accessing the dispatcher internals will be specified in another TIP. The primitive commands \(like **my**, **next**, **self**, **configure**, ...\) are provided by the OO namespace, and these can be provided by the extension writers by accessing the dispatcher structure and its stack. # Strengths of the Approach * All OO extensions can use the powerful dispatcher * If a certain extensions don't require filters, mixins, etc., they simply don't have to activate these. * The XOTcl dispatcher can be seen as a prototype implementation, but it should be replaced by a more efficient implementation with tighter core integration, provided the regression tests of the languages \(e.g., XOTcl\) continue to work. * The prototype implementation based on the current XOTcl 1.5.3 alpha release > \* is proven to work and sufficiently bug-free, > \* is free of memory leaks, > \* thread safe, > \* provides execution of the destroy callbacks when a thread or program exits, > \* provides uplevel transparency for interceptors, > \* is well suited for IDEs \(an arbitrary class from a class tree can be reloaded and redefined without altering the relations between classes and/or instances\) * All OO systems are treated equal > \* since we do not want to allow to register methods on **::oo::object** or **::oo::class**, there is no "preferred" object system, > \* every object system defines its own classes with its own names and own methods \(although, it can reuse methods from all extensions with arbitrary names, as shown above\) > \* there is no need to namespace export from "oo::\*" \(these are no end-user commands\). > \* nobody is forced on any predefined semantics * no extensions are locked out > \* existing "high level" extensions \(like XOTcl\) and their applications \(e.g. OpenACS\) continue to work > \* since other OO language definitions are not part of the core, their development can continue, > \* other OO languages can easily benefit from the new core functionality > \* the dispatcher is based on a superset of the requirements of existing languages, so these should be able to use it. > \* extending the dispatcher requires a TIP. * This proposal is in the Tcl tradition of Tcl as a 2-level meta-language, since it provides a highly adjustable framework for object oriented languages. * Providing such a framework will attract people and put Tcl in front of the other OO scripting languages. # Sample Implementation * XOTcl 1.5.3alpha is the reference dispatcher \(it should be rewritten for inclusion in the core, and serves here only as proof-of-concept\) <http://media.wu-wien.ac.at/download/xotcl-1.5.3-alpha2.tar.gz> . * Example of the TclCOOL language \(to be the _part_ of the framework\) <http://media.wu-wien.ac.at/download/tcl-cool.tcl> * Example of a subset of ITcl based on this TIP \(implemented with the framework, runs already part of the itcl regression tests: protection.test and basic.test, in the latter, only three error messages differ\) <http://media.wu-wien.ac.at/download/itcl.tcl> * Example of the XOTcl language \(as implemented _with_ the framework\): See generic/predefined.xotcl in the XOTcl 1.5.3alpha reference implementation # Copyright This document has been placed in the public domain. |
Name change from tip/28.tip to tip/28.md.
|
| < | < | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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 | # TIP 28: How to be a good maintainer for Tcl/Tk Author: Don Porter <[email protected]> State: Draft Type: Informative Vote: Pending Created: 23-Feb-2001 Post-History: ----- # Abstract This document presents information and advice to maintainers in the form of a Frequently Asked Questions \(FAQ\) list. # Preface Notice in the header above that this is a Draft document. It won't be the _official_ word of the TCT unless/until it is accepted by the TCT. Meanwhile, it should still be a helpful guide to those serving or considering service as maintainers. At the very least it's a useful straw man to revise into something better. Help us make it even more useful by using the [Edit] link at the bottom of this page \(if any\) to add/revise the questions and answers, or add your comments. # Background TCT procedures \(see [[0]](0.md)\) calls for one or more _maintainers_ to take responsibility for each functional area of the Tcl \([[16]](16.md)\) or Tk \([[23]](23.md)\) source code. Every source code patch to Tcl or Tk will be committed to the official branches of the appropriate CVS repository only after approval by an appropriate set of maintainers. # Can I be a Tcl/Tk maintainer? Most likely. To be a maintainer, you should have... * ...an interest in Tcl/Tk. * ...access to the Internet \(Web and e-mail\). * ...some volunteer time to contribute. * ...the ability and the support software to code in C and/or Tcl, use CVS, use SourceForge facilities, and familiarity with a portion of the Tcl/Tk source code to be maintained, or the willingness to acquire these things. For the most part, if you are reading this document, you probably have what it takes to be a Tcl/Tk maintainer. # What can I maintain? The Tcl Core Team \(TCT\) has divided up the Tcl/Tk source code into functional areas as described in [[16]](16.md) and [[23]](23.md). You can volunteer to help maintain as many areas as you think you can handle. Select those you have experience with or an interest in. # What does a maintainer do? Maintainers are the people who make changes to the files that make up the source code distribution of Tcl or Tk -- code, documentation, and tests. That's what a maintainer does: check in changes to the official source code in the area he/she maintains. The source code can be changed for several reasons: to correct a bug, to add a new feature, or to re-implement an existing feature in a new way. The reason for a change controls how much oversight the maintainer must have while making the change. More on this below. # How do I prepare to be a maintainer? The official repositories of Tcl and Tk source code are kept at SourceForge, so you need to register for a SourceForge account <https://sourceforge.net/account/register.php> . As part of the registration, you will select a login name. When you volunteer as a maintainer, the administrators of the Tcl or Tk projects will need that name to give you write access to the appropriate repository. Once you have a SourceForge account, get familiar with the tools it provides. Most important is that you get set up to use CVS over SSH to access the repository. This can be difficult. There are some notes <http://tcltk.org/sourceforge> on how other Developers on the Tcl and Tk projects have been able to successfully get this done. This document does not include instructions on how to use CVS. See the following references for assistance with learning CVS. * <http://cvsbook.red-bean.com/cvsbook.html> _Add more references here please._ # How do I volunteer to be a maintainer? Send a message to <[email protected]> telling the TCT your SourceForge login name and what area\(s\) you want to help maintain. Someone will add you to the list of _Developers_ on the Tcl or Tk projects and enable your access to SourceForge features like the Bug Tracker and Patch Manager. As a Developer, you will have write access to the appropriate repository of official source code. # Write access! So I can just start changing Tcl/Tk?! For some purposes, yes. For others, you'll need to get approval from the TCT first. Read on... # What Internet resources does a maintainer use? A maintainer uses the SourceForge Bug Tracker for Tcl or Tk to learn what bugs are reported in his area \(browse by Category\). * <http://sourceforge.net/bugs/?group\_id=10894> * <http://sourceforge.net/bugs/?group\_id=12997> A maintainer uses the SourceForge Patch Manager for Tcl or Tk to learn what patches make changes in his area \(browse by Category\). * <http://sourceforge.net/patch/?group\_id=10894> * <http://sourceforge.net/patch/?group\_id=12997> A maintainer uses CVS via SSH to access, track, and modify the various branches of development in the repository of official Tcl or Tk source code. cvs -d :ext:[email protected]:/cvsroot/tcl \ checkout -r $BRANCH_TAG -d $LOCAL_DIR tcl cvs -d :ext:[email protected]:/cvsroot/tktoolkit \ checkout -r $BRANCH_TAG -d $LOCAL_DIR tk A maintainer examines the state of Tcl Improvement Proposals \(TIPs\) and adds his comments to them at the TIP Document Collection. * <http://purl.org/tcl/home/cgi-bin/tct/tip/> A maintainer may follow and participate in TCT discussions about TIPs and other matters concerning Tcl/Tk development on the TCLCORE mailing list. * <http://lists.sourceforge.net/lists/listinfo/tcl-core> A maintainer may receive e-mail notification every time any change is made to any entry in Tcl's or Tk's Bug Tracker or Patch Manager by subscribing to the TCLBUGS mailing list. * <http://lists.sourceforge.net/lists/listinfo/tcl-bugs> # There are multiple maintainers in my area. What do I do? The maintainer tasks are the same; you just have more hands to get the job done. It is up to the maintainers of an area to decide among themselves how they will divide the tasks. They might each take on a particular subset of files. Or they might let some maintainers fix bugs while others review new features. Or they might appoint one maintainer as the _lead_ and let him assign tasks to the others. Whatever works for you, and gets the work done. # I found a bug in my area. What do I do? Bug finding and reporting is a job for the whole community, so when you find a bug, take off your maintainer hat. Report it to the Bug Tracker just like anyone would. If you recognize that the bug is in your area, go ahead and assign it to the Category for your area and to yourself or one of the other maintainers who share responsibility for that area. # Why do I report the bug to myself? So that the bug appears in the database. Someone else may find it too, and when they go to report it to the Bug Tracker, they should discover that it's an already reported problem. A registered bug report is also the place where progress on fixing the bug can be recorded for all to see. # There's a bug reported in the Category for the area I maintain. What do I do? First, understand the bug report. The best bug reports are clear and come with a demonstration script, but not all reports are so well crafted. You may need to exchange messages with the person who reported the bug. If the reporter logged in to SourceForge as _username_ before submitting a report, then you can write back to _[email protected]_. If the bug was reported by _nobody_, the best you can do is post a followup comment to the bug asking for more information, and hope the reporter comes back to check. Next, confirm that the bug report is valid, original, and that it belongs in your area. Does it correctly assert that some public interface provided by your area behaves differently from its documented behavior? If not, then you should take the appropriate action: 1. If the bug report notes a problem in another project, assign it to a Developer who is an Admin of the other project. Add a comment asking them to reassign to the correct project. Assigned To: _an Admin of the other project_. > If no Developer is an Admin of the other project, or the other project isn't hosted by SourceForge, note the error in a comment, and mark the report invalid. Resolution: Invalid; Status: Closed; Assigned To: _yourself_. 1. If the bug report notes a problem due to a bug in another area, reassign it to the appropriate Category. Category: _correct category_ 1. If the reporter's expectations are incorrect, point them to the documentation. You may also want to revise the documentation if it is not clear. Resolution: Invalid; Status: Closed; Assigned To: _yourself_. 1. If the bug report notes a problem already noted by another bug report, note the duplication. Resolution: Duplicate; Status: Closed; Assigned To: _yourself_. 1. If the bug report acknowledges that the code is behaving as documented, but argues that the documented behavior should be revised, then the report is a feature request rather than a bug report. More on handling feature requests below. Group: Feature Request. Valid, original bug reports in your area should be assigned to a maintainer of your area. If you are the only maintainer of your area, assign the bug to yourself. If there are multiple maintainers, you should decide among yourselves how to divide up the bug report assignments. # There's a bug assigned to me. What do I do? Now we get the the heart of what a maintainer does. This is where you unleash the energies and talents you bring to the table. So, the best answer is "Do what works best for you." The rest of this answer should be read as additional guidelines and tips that have worked well for others and might help you, but not as a mandatory checklist you must follow. If some advice below seems more burdensome than helpful, fall |
︙ | ︙ | |||
267 268 269 270 271 272 273 | feature is added to Tcl/Tk. In those cases, add a comment to the original bug report so those interested will know what is causing the delay. SourceForge may offer a way to denote these dependencies as well. If you have trouble fixing the bug, ask for help. Try the other maintainers of your area first. Then try posting comments attached to | | | 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 | feature is added to Tcl/Tk. In those cases, add a comment to the original bug report so those interested will know what is causing the delay. SourceForge may offer a way to denote these dependencies as well. If you have trouble fixing the bug, ask for help. Try the other maintainers of your area first. Then try posting comments attached to the original bug report. Using _cvs log_, you can get a list of developers who've recently made changes to the files you maintain. They might be able to offer advice, or explanations about why the code is the way it is. If none of these focused searches for help bears fruit, then try broader requests to the TCLCORE mailing lists, or the news:comp.lang.tcl newsgroup. At any time, you may have several bugs assigned to you. It will help |
︙ | ︙ | |||
291 292 293 294 295 296 297 | 1. Other bug fixes are waiting on this bug fix. 1. Several duplicate reports or "me too" comments about the bug are coming in from the community. Some reasons you might give a bug a lower priority include: | | | | | | | | | | | | | | | | | | | | | | | | 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 | 1. Other bug fixes are waiting on this bug fix. 1. Several duplicate reports or "me too" comments about the bug are coming in from the community. Some reasons you might give a bug a lower priority include: 1. A workaround is identified \(add it as a comment attached to the bug report\). 1. Feature requests tend to get lower priority since they should be handled through the TIP process. Once you have crafted a fix for the bug, create a patch to the official source code \(including the new tests that test for the fixed bug\) and register it with the SourceForge Patch Manager. Note the number of the bug report fixed by the patch somewhere in the summary or comments associated with the patch. Assign the patch to yourself. Assign the Category to the area you maintain. # There's a patch registered under the Category I maintain. What do I do? The SourceForge Patch Manager is used to review and revise patches before they are committed to the official source code. Your actions depend on what the patch does to your area, and who the patch is assigned to. The patch may change the public interface provided by your area \(feature change\); or the change may be completely internal \(bug fix, or re-implementation\) within your area. The patch may be assigned to you, to someone else, or to nobody. The person the patch is assigned to is the person who is leading the effort to integrate the patch into the official source code. # What if the patch is assigned to nobody? The patch has probably been contributed by someone not on the list of Developers. It may be a contributed bug fix, or a contributed implementation of a TIP. Assign contributed bug fixes to the same maintainer who is assigned the corresponding bug report. If there is no corresponding bug report, add one. Assign TIP implementations to the Developer identified in the TIP as the one responsible for implementation of that TIP, or the TCT member who sponsored the TIP. If the patch changes only your area \(and shared or generated files\), then leave the Category in your area. If the patch changes other areas as well as yours, change the category to None. # What if the patch is assigned to me? Presumably you've assigned it to yourself to indicate that you're taking charge of integrating that patch into the official sources. If that's a mistake, treat the patch as if it were assigned to nobody. If you are the one leading the integration effort, see below \(How do I integrate a patch into the official sources?\). # What if the patch is assigned to someone else? If the patch is assigned to another maintainer in your area, let him handle it. Leave it alone. If the patch makes no changes in your area, change the Category of the patch to None. If the patch makes changes in your area, and is assigned to a Developer who is not a maintainer of your area, that Developer is asking for review of the patch's changes to your area. You or one of the other maintainers of your area should review the patch and accept or reject it. Read on... # What special review does a "feature change" patch require? Changes to the public interface of your section must be proposed to and accepted by the TCT through the TIP process before they can be added to the official Tcl source code. If the patch changes the public interface of your section, then there should be an associated TIP describing the new feature\(s\) that patch implements. Until there is such a TIP, and that TIP has been accepted by the TCT \(check the value of the State header\), you should not approve the patch. Once there is an approved TIP corresponding to the patch, you should confirm that the patch correctly implements the accepted feature as described by the TIP. If not, you should not approve the patch. After confirming that the patch correctly implements the feature change described in an accepted TIP, you should still review the technical merit of the patch's changes to your area before approving it. # How do I review the technical merits of a patch? Apply the patch and run the test suites that cover your area. Check that the patch does not add any new test failures. If the patch is a bug fix, check that it actually fixes the bug. Think five times before approving a patch that causes new test failures or incompletely fixes a bug or incompletely implements an approved TIP. Keep in mind that once the patch is integrated into the official sources, you'll be expected to maintain it. It is not in your interest to approve patches that make your job harder. Think four times before approving a patch that you do not understand. Check that the patch keeps the features offered on different platforms consistent. If not, be certain that the documentation properly notes the platform-specific behavior. Think three times before approving a patch that causes the capabilities of Tcl/Tk to further diverge on different platforms. Check that the patch follows Tcl's established coding conventions. See the Tcl/Tk Engineering Manual <http://purl.org/tcl/home/doc/engManual.pdf> and the Tcl Style Guide <http://purl.org/tcl/home/doc/styleGuide.pdf> for details. This is especially important when accepting contributed patches. Think twice before approving a patch that doesn't conform to these conventions. Check the effect of the patch on the performance of Tcl/Tk. Use the tclbench set of benchmarks. cvs -d :pserver:[email protected]:/cvsroot/tcllib \ checkout tclbench Think carefully before approving a patch that significantly degrades the performance of important operations. Finally, while examining the patch, you may see a better way to accomplish the effect of the changes in your area. If you can provide that alternative implementation reasonably quickly, then propose it as |
︙ | ︙ | |||
430 431 432 433 434 435 436 | you can supply the needed revisions with reasonable effort, do so. If the patch changes multiple areas, set the Category of the patch back to None. Unless the patch is assigned to you, do not change the Status of the patch. Leave that to the Developer assigned to the patch. | | | | | | | | | | | | | | | | | | > | 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 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 | you can supply the needed revisions with reasonable effort, do so. If the patch changes multiple areas, set the Category of the patch back to None. Unless the patch is assigned to you, do not change the Status of the patch. Leave that to the Developer assigned to the patch. # How do I integrate a patch into the official sources? First you need the approval of at least one maintainer of each section changed by the patch. # How do I get approval for integration? First, assign the patch to yourself to indicate that you are leading the integration effort. Next, determine the list of categories corresponding to the areas changed by the patch. It may help if you list them in a comment attached to the patch. For each category in the list, assign the Category of the patch to that category. Then wait for a maintainer for that area to review the patch. If one approves it, then assign the next Category in the list. If maintainers for all areas on the list approve the same patch, you may integrate the patch into the official sources. If a maintainer rejects the patch, revise the patch to address his concerns. Then start the review again. Start with the maintainer who rejected the first patch to be sure his concerns are addressed first. Note that if the patch changes only the area you maintain, then you may immediately integrate the patch into the official sources once you are satisfied with it and it is registered in the Patch Manager. # The patch is approved. How should it be integrated? Get a CVS working directory that is up to date with the HEAD branch of the official source repository. Apply the patch to your working directory, and then 'cvs commit' the changes to the HEAD branch. At the same time you commit the patch, be sure to add an entry to the ChangeLog file describing the change. Follow the established format, which is derived from the GNU coding conventions. The description should be brief, but should describe the change reasonably completely. Include the SourceForge Bug and Patch ID numbers in the ChangeLog entry, but do not assume that the reader will have access to the Bug Tracker and Patch Manager to be able to understand the entry. You may assume the reader has access to the documentation. Finally, with the patch integrated, change the Status of the patch in the Patch Manager to Accepted. If any bugs were fixed by the patch, change their Resolution to Fixed, and their Status to Closed. # I want a patch review even though the patch changes only my area. Keep in mind that integrating a patch into the official sources is not an irreversible act. Commits to the HEAD branch will be checked out and tested by members of the Tcl community who are tracking Tcl/Tk development. Alpha and beta releases of Tcl/Tk that include your patch will also get your changes reviewed in practical settings. That said, if you really want a pre-commit review of your patch, you can add a comment to the patch asking for review. Someone will probably respond. It's up to your judgment how long to wait, keeping in mind that you are the maintainer, so your judgment on the quality of patches in your area is implicitly trusted. # What about CVS branches? When you integrate a patch into the official source code, you will usually 'cvs commit' the patch onto the HEAD branch. If the patch includes a feature change, it must \(except in unusual circumstances approved by the TCT\) be committed to the HEAD branch. The HEAD branch is the development branch from which alpha releases of Tcl/Tk are generated. At any time, there is also one or more _stable_ branches of development. As of February, 2001, the branch 'core-8-3-1-branch' indicates the sequence of revisions from which the 8.3.x releases of Tcl/Tk are generated. Since the Tcl Core Team took over development of Tcl/Tk, no changes have been committed to a stable branch, so we really have not established procedures on how we will decide what bug fixes should and should not be applied to the stable branch. It is possible that maintainers will be involved, though. It is also possible that a special team will be appointed to update the stable branch in preparation for the next stable release. In the case that you as a maintainer are asked to commit to the stable branch, be aware that the only patches that should be committed to a stable branch are those that fix bugs. No new features should be committed here. The other kind of branch is a _feature_ branch. This is a development branch on which a sequence of several revisions may be committed as work in progress on a new feature, or re-implementation of existing features. Typically a feature branch will be created if the effort... * ...touches on several functional areas; * ...is worked on jointly by several Developers; * ...is complex enough to require several revisions; * ...needs prototyping to determine the best TIP proposal to make; or * ...makes an incompatible change to Tcl/Tk that properly belongs on the next major version of Tcl/Tk before the HEAD branch has been designated for work toward the next major version. As a Developer, feel free to create a feature branch if you have a reason to use one. Make a note of your branch tags in [[31]](31.md). Avoid the use of a branch tag matching core-\* . Save the core-\* branch tags for the tags of official stable branches and releases. To avoid conflict with other Developers, consider using your SourceForge login name as a prefix on the feature branch tags you create. Try to also make the branch tag descriptive of the purpose of the branch. One big advantage of a feature branch is that any Developer may commit changes to a feature branch without all the publication, review, and approval overhead required when committing patches to the HEAD or stable branches. On the feature branches you can go through multiple revisions reasonably quickly and spend the administrative overhead only at the end when it is time to apply the finished product to the official branches. # What other things does a maintainer do? The tasks of fixing bugs and approving and committing patches to the official source code of Tcl and Tk are the core tasks that maintainers perform. That's all the job actually requires. You will probably want to keep an eye on the TCT's plans for Tcl/Tk development as well. If a TIP proposes a new feature in your area, it is in your interest to know about it, and propose revisions and improvements to it. Ultimately you will be asked to approve the patch that implements the new feature, and then you will be expected to maintain it, so if you have concerns about a proposal, it's best to make them known early. TCT members will probably ask your opinion on TIPs that propose changes to your area for this reason. # Comments Please add your comments here. > Well, since I drafted this SourceForge has replaced the Bug Tracker and Patch Manager with a _Tracker_. This TIP _really_ needs revision now. # Copyright This document has been placed in the public domain. |
Name change from tip/280.tip to tip/280.md.
|
| < | < | | | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | < | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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 | # TIP 280: Add Full Stack Trace Capability With Location Introspection Author: Andreas Kupries <[email protected]> Author: Andreas Kupries <[email protected]> State: Final Type: Project Vote: Done Created: 10-Aug-2004 Post-History: Keywords: Tcl Obsoletes: 211 Tcl-Version: 8.5 ----- # Abstract This TIP proposes adding a new subcommand to the **info** command to get a list of all the frames on the current stack, with additional information about command location, type of execution, etc., rather than the limited list returned by **info level**. It is also related to Peter MacDonald's [[86]](86.md), or rather, to the **info linenum** feature proposed there. The base feature of providing location information for a command was extended, allowing the user to ask for the current location in all stack levels. Enough information is returned to consider this as an extended [[211]](211.md). # Rationale The motivation for this feature is the debugging of scripts in situations where an error stack is wanted, to see where the problem occurred, but aborting the execution is not desired. To enable this a means of providing the essential information shown in an error stack is needed, which does not require an abort \(and subsequent unwinding of the C stack\) to assemble this information. An example is the testing of scripts where an unexpected error should not fail the test case, nor the framework, yet still allow the recording of the problematic location and how it was reached in some log. The original motivation for [[211]](211.md) was that there is currently no way to get a list of all the frames in the current stack managed by **Tcl\_PushCallFrame\(\)** and **Tcl\_PopCallFrame\(\)**. The **info level** command does not contain frames that are callers of **uplevel**, reporting only the frames that are accessible via another **uplevel** command. There are times when the lack of information can have a negative impact on code design. This motivation asks in essence for an error stack as well, but limited itself to the returning commands themselves, and not the other information, like the line the command is on, its context, etc. Other use cases, also found in [[211]](211.md): 1. **tcltest**, and other testing frameworks. > The first case is with the core's Tcltest package, where the complete lack of ability to gain access to that information means it is impossible to gain information about a test without modifying the Tcltest code itself. Being able to find out the caller info would be very useful, especially for logging information. Currently, there is no way to get the caller's info, due to the fact that the code for the test is _uplevel_ed and, hence, not visible via **info level**. 2. **TestStubs Package** > The TestStubs package provides the ability to temporarily redefine commands, in particular for stubbing out or replacing functionality in a test case. There is a command in the package called **chain**, which is used within the code replacing a command \(or part of a command\) to call the original definition of the command. For example, one could do: stubs::stub ensemble array names { return [lsort [uplevel 1 chain names $args]] } > However, since the **chain** command is \(and should be\) limited to only running from within a stub definition, it needs to call **info level** to find out if its caller is one of the stubbed commands, and what the name of that command is. With **info level**, it would not have access to the level that is running inside the stubbed procedure. Hence, either it cannot check this constraint, or stubs cannot be allowed to use **uplevel** when calling it \(which means things like the above either cannot work, or need to be rewritten in a considerably less clear manner\). # Specification of the Proposed Change ## Tcl Level API The builtin command **info** is extended to accept a new subcommand, **frame**. When this subcommand is called it returns information about the current command and its location. This information is available not only for the current stack level, but also the higher stack levels used to reach the current location. The syntax of the new subcommand is > **info frame** ?_level_? The new functionality will provide access to all frames on the stack rather than the current limited subset. This TIP does _not_ propose to alter **uplevel** or **upvar** so that they can see these hidden levels. If _level_ is not specified, this command returns a number giving the frame level of the command. This is 1 if the command is invoked at top-level. If _level_ is specified, then the result is a dictionary containing the location information for the command at the _level_ on the stack. If _level_ is positive \(> 0\) then it selects a particular stack level \(1 refers to the top-most active command, i.e., **info frame** itself, 2 to the command it was called from, and so on\); otherwise it gives a level relative to the current command \(0 refers to the current command, i.e., **info frame** itself, -1 to its caller, and so on\). This is similar to how **info level** works, except that this subcommand reports all frames, like **source**'d scripts, **eval**s, **uplevel**s, etc. Note that for nested commands, like "foo [bar [x]]" only "x" will be seen by an **info frame** invoked within "x". This is the same as for **info level** and error stack traces. The result dictionary may contain the keys listed below, with the specified meanings for their values. * **type** > This entry is always present and describes the nature of the location for the command. The recognized values are **source**, **proc**, **eval**, and **precompiled**. > In some circumstances it makes sense to have this information extensible, i.e. to allow user-defined type names. For more about this topic see the discussion at the end of the document. > \* **source** means that the command is found in a script loaded by the **source** command. > \* **proc** means that the command is found in dynamically created procedure body. > \* **eval** means that the command is executed by **eval** or **uplevel**. > \* **precompiled** means that the command is found in a precompiled script \(loadable by the package _tbcload_\), and no further information will be available. * **line** > This entry provides the number of the line the command is at inside of the script it is a part of. This information is not present for type **precompiled**. For type **source** this information is counted relative to the beginning of the file, whereas for the last two types the line is counted relative to the start of the script. * **file** > This entry is present only for type **source**. It provides the normalized path of the file the command is in. * **cmd** > This entry provides the string representation of the command. This is usually the unsubstituted form, however for commands which are a pure list executed by eval it is the substituted form as they have no other string representation. Care is taken that the pure-List property of the latter is not spoiled. * **proc** > This entry is present only if the command is found in the body of a regular Tcl procedure. It then provides the name of that procedure. * **lambda** > This entry is present only if the command is found in the body of an anonymous Tcl procedure, i.e. a lambda. It then provides the entire definition of the lambda in question. * **level** > This entry is present only if the queried frame has a corresponding frame returned by **info level**. It provides the index of this frame, relative to the current level \(0 and negative numbers\). A thing of note is that for procedures statically defined in files the locations of commands in their bodies will be reported with type **source** and absolute line numbers, and not as type **proc**. The same is true for procedures nested in statically defined procedures, and literal eval scripts in files or statically defined procedures. In contrast, for a procedure definition or eval within a dynamically eval'uated environment count linenumbers relative to the start of their script, even if they would be able to count relative to the start of the outer dynamic script. That type of number usually makes more sense. A different way of describing this behaviour is that we track file based locations as deeply as we can, and where we cannot the lines are counted based on the smallest possible eval or procbody scope, as that scope is usually easier to find than any dynamic outer scope. The syntactic form **\{expand\}** is handled like **eval**. This means that if it is given a literal list argument the system tracks the line-number within the list words as well, and otherwise all line-numbers are counted relative to the start of each word \(smallest scope\) The following other builtin commands are changed as well to support the tracking of line numbers: 1. catch 1. dict for |
︙ | ︙ | |||
230 231 232 233 234 235 236 | 1. source 1. switch 1. while | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | < > | | | | | | | | | < > | | | | | | < | > | | | | | | | | | | | | | | | | | < > | | | | | > | 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 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 | 1. source 1. switch 1. while ## Public C API No changes are made to the public C API. # Examples Note that this is not a complete set of examples covering all possible cases. Let us assume that the file is named EX. The "cmd" is always the "info frame ..." command, and "level" is 0 too, always, in this situation. This is left out of the result dictionaries to keep them small. puts [info frame 0] ;# 01* - output: {cmd {info frame 0} line 1 file EX type source} ;# 02 proc foo {} { ;# 03 /foo remembers 3 puts [info frame 0] ;# 04* } ;# 05 foo ;# 06 - output: {cmd {...} line 4 file EX type source} ;# 07 set script { ;# 08 1 puts [info frame 0] ;# 09 2* } ;# 10 3 eval $script ;# 11 - output: {cmd {...} line 2 type eval} ;# 12 eval { ;# 13 1 puts [info frame 0] ;# 14* 2* } ;# 15 3 - output: {cmd {...} line 14 type source} ;# 16 proc fox {} { ;# 17 /fox remembers 17 eval $::script ;# 18 } ;# 19 fox ;# 20 - output: {cmd {...} line 2 type eval} ;# 21 proc squirrel {} { ;# 22 /squirrel remembers 22 eval { ;# 23 1 puts [info frame 0] ;# 24* 2* } ;# 25 3 } ;# 26 squirrel ;# 27 - output: {cmd {...} line 24 type source} ;# 28 proc fuchs {} { ;# 29 /fuchs remembers 29 proc dog {} { ;# 30 1 /dog remembers 30 puts [info frame 0] ;# 31* 2* } ;# 32 3 } ;# 33 fuchs ;# 34 dog ;# 35 - output: {cmd {...} line 31 type source} ;# 36 eval { ;# 37 1 proc wolf { ;# 38 2 /wolf remembers 38 puts [info frame 0] ;# 39* 3* } ;# 40 4 } ;# 41 5 wolf ;# 42 - output: {cmd {...} line 39 type source} ;# 43 set scripted { ;# 44 1 proc deer {} { ;# 45 2 /deer remembers 2 puts [info frame 0] ;# 46 3* } ;# 47 4 } ;# 48 5 eval $scripted ;# 49 deer ;# 50 - output: {cmd {...} line 3 type eval} ;# 51 puts [set a b ;# 52 info frame 0] ;# 53* - output: {cmd {...} line 53 type source file EX} ;# 54 puts [info \ frame 0] ;# 56 - output: {cmd {...} line 55 type source file EX} ;# 57 proc salmon {} \ { ;# 59 puts [info frame 0] ;# 60* } ;# 61 salmon ;# 62 - output: {cmd {...} line 60 type source file EX} ;# 63 set method frame ;# 64 puts [info $method 0] ;# 65* - output: {cmd {info $method 0} line 65 type source file EX} ;# 66 proc trout {} { ;# 67 puts [info $method 0] ;# 68* } ;# 69 trout ;# 70 - output: {cmd {info $method 0} line 68 type source file EX} Another example showing how to query the whole stack of frames. It assumed that the file is named EX. The output shown after the example was manually reformatted to explicitly ordered the keys and the columns vertically aligned, for readability and better comparability of the lines. The returned level information was removed, and level numbers for **info frame** were added at the beginning of the lines. proc setRes {result} { ;# 01 if {$result == "fail"} { ;# 02 set level [info frame] ;# 03 while {$level} { ;# 04 puts [info frame $level] ;# 05 incr level -1 ;# 06 } ;# end of while ;# 07 } ;# end of if ;# 08 } ;# end of proc setRes ;# 09 proc runTest {tc} { ;# 10 # run the testcase ;# 11 uplevel 1 setRes fail ;# 12 } ;# end of proc runTest ;# 13 runTest TC0001 ;# 14 **Output:** 4 {cmd {runTest TC0001} line 14 type source file EX} 3 {cmd {uplevel 1 setRes fail} line 12 type source file EX proc runTest} 2 {cmd {setRes fail} line 1 type eval} 1 {cmd {info frame $level} line 5 type source file EX proc setRes} To see the connection between the new feature and error stack traces replace the **info frame** command on line 3 of _setRes_ with "**return** -code error X". This will generate an error trace and with a bit of reformatting the relationship can be seen easily: **Stack trace:** X while executing "setRes fail" ("uplevel" body line 1) invoked from within "uplevel 1 setRes fail" (procedure "runTest" line 3) invoked from within "runTest TC0001" (file "EX.tcl" line 14) Reformat the trace, with all output from a single command on one line, and some noise removed. X "setRes fail" ("uplevel" body line 1) "uplevel 1 setRes fail" (procedure "runTest" line 3) "runTest TC0001" (file "EX.tcl" line 14) Now revert the order of the lines, and add vertical alignment. Now have in essence the ouput of the unmodified example, with same difference in the line numbers. But that is only because the error stack trace always counts lines relative to the script, and doesn't attempt to determine an absolute location in a file. "runTest TC0001" (file "EX.tcl" line 14) "uplevel 1 setRes fail" (procedure "runTest" line 3) "setRes fail" ("uplevel" body line 1) X ## Child Interpreters The current implementation of **info level** only returns levels up to the top of the stack for the current interpreter. Such an approach puts limitations on what information can be retrieved, but allows for a certain level of "_security_" when running code in child interps, especially safe interps. Given the security considerations of safe interps, and consistancy with regards to what information is returned across multiple circumstances, the stack trace returned will only return information up to the top level of the current interp, the same limit **info level** is bound by. # Discussion A point noted by Lars Hellstrom is that this TIP makes the builtin **source** command special. It is not possible anymore to re-create **source** purely in Tcl, doing so will loose the name of the file. We are still tracking line numbers, but they are then relative to the start of the eval'd script, withut a connection to the file. In a similar way, user-defined control structures lose the ability of the builtin _if_, etc. to track line numbers in a literal code block relative to the enclosing file. The user-defined commands are again reduced to providing line numbers relative to the start of the code block. To bring user-defined commands back to the same level as the builtins we need: 1. An extension of **info frame** which delivers the line information for all words of the command we are inside of. As each word can start on a different line \(because of continuation lines and preceding multi-line literals\). > This information is actually already available internally. The current implementation needs it for the tracking into literals. 1. Extensions to the _uplevel_ and _eval_ commands which allow a script to provide them with location information for the script they are evaluating. For example: proc newsource {foo script} { ... preprocess whatever ... set loc [info frame data for word 2] uplevel -location $loc 1 $script } Internally we also need quite a bit more flexible data structures. The type names for example are defined through a C enum, and can be checked quickly and efficiently. The file information, i.e. path, is stored and used dependent on that, only for type **source**. To keep this TIP and its implementation reasonably small the actual detailed specification and implementation of such extensibility is defered to a future TIP. # Reference Implementation An implementation patch is available on SourceForge<http://sourceforge.net/support/tracker.php?aid=1571568> . # Copyright This document has been placed in the public domain. Please note that any correspondence to the author concerning this TIP is considered in the public domain unless otherwise specifically requested by the individual\(s\) authoring said correspondence. This is to allow information about the TIP to be placed in a public forum for discussion. |
Name change from tip/281.tip to tip/281.md.
|
| < | < | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 281: Improvements in System Error Handling Author: David Gravereaux <[email protected]> State: Draft Type: Project Vote: Pending Created: 08-Oct-2006 Post-History: Keywords: POSIX,channel driver,errorCode Tcl-Version: 8.7 ----- # Abstract This TIP describes the need for better error codes and message handling of system errors to be returned to scripts. # Rationale The current method for handling of system errors is done via the _Tcl\_PosixError\(\)_ API call. Its job is to grab the value of _errno_ and format it for display to a script within the **errorCode** special variable. Unfortunately, not all such system errors are left in _errno_ and on Windows, not all information can be translated effectively to a POSIX error code without loss of valuable information to the user. On UNIX, _gethostbyname\(\)_ for example, leaves its errors in _h\_errno_ <http://www.opengroup.org/onlinepubs/009695399/basedefs/netdb.h.html> . If we look at our use of _gethostbyname\(\)_ in unix/tclUnixChan.c for the _CreateSocketAddress\(\)_ function, you'll see we are setting _errno_ to a wrong code rather than retrieving the proper error information defined in _netdb.h_. An example of the current mistranslation would be: % socket foo.example.com 1234 couldn't open socket: host is unreachable % set errorCode POSIX EHOSTUNREACH {host is unreachable} And on Windows: % socket foo.example.com 1234 couldn't open socket: invalid argument % set errorCode POSIX EINVAL {invalid argument} Notice that the two are different as well as wrong. EHOSTUNREACH is a routing error at the IP level and is returned by connect\(\), send\(\).. etc., not by gethostbyname\(\). For windows, the error translation function TclWinConvertWSAError\(\) sets _errno_ to EINVAL for a WSAHOST\_NOT\_FOUND even though the code in CreateSocketAddress\(\) appears to set errno to EHOSTUNREACH. What I would like to see is the following \(on all platforms\): % socket foo.example.com 1234 couldn't open socket: No such host is known % set errorCode NETDB HOST_NOT_FOUND {No such host is known} If we could specify a place from where the error could be retrieved along with the formatting functions for that type, Tcl's error information to the user would be improved. A facility to extend/add formatters would also help extension authors. For example with the windows port of Expect, there are numerous specific errors that Expect could return regarding how the Console API debugger was unable to function, but the error path is only limited to POSIX pipe errors rather than anything specific. I tried to make a facility to manage these specific errors in a controlled way using a message catalog <http://www.pobox.com/~davygrvy/expect-src/win/expWinErr.mc> to compile into the expect dll a "windows"-ish style of error management along with a specific "EXPECT" formatter, see ExpWinError\(\) [last function in file] <http://www.pobox.com/~davygrvy/expect-src/win/expWinUtils.cpp> . I used the "customer" bit in the **errorCode** as a key to forward to the "WINDOWS" formatter and thought it was quite smart of me. But alas... the POSIX restriction was not to be bypassed in a manageable manner. # Reference Implementation A reference implementation is not done at this time. An experimental WINDOWS **errorCode** formatter can be seen @ <http://iocpsock.cvs.sourceforge.net/iocpsock/iocpsock/tclWinError.c?revision=HEAD&view=markup> # Copyright This document is in the public domain. |
Name change from tip/282.tip to tip/282.md.
|
| < | < | | | | | | | | | > | | | | | | | | | | | | | | | | < > | | | | | | | | | | | > | 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 | # TIP 282: Enhanced Expression Syntax Author: Will Duquette <[email protected]> Author: Don Porter <[email protected]> State: Draft Type: Project Vote: Pending Created: 13-Oct-2006 Post-History: Keywords: expr,operator,assignment Tcl-Version: 8.7 ----- # Abstract This TIP extends the syntax of the **expr** command to allow a sequence of mathematical computations to be expressed clearly and concisely. # Rationale The ugliness of mathematical code written in Tcl is a perennial source of complaint. Consider the following computation: set x [expr {5*$y + 6*$z}] set w [expr {$x**2 + $y**2}] set v [expr {$w**2 + $y**2}] The [**expr {...}**] constructs make the code considerably harder to read. But suppose **expr** syntax included an assignment operator: expr {x = 5*$y + 6*$z} expr {w = $x**2 + $y**2} expr {v = $w**2 + $y**2} Next, suppose that an **expr** expression could include subexpressions, delimited by a ";" character: expr { x = 5*$y + 6*$z; w = $x**2 + $y**2; v = $w**2 + $y**2 } The sequence of computations is now much clearer. # Specification ## Assignment Operator The **expr** syntax should be extended with an assignment operator which has C-like semantics, i.e., the result of an assignment is the assigned value. This operator shall be written as "**=**". The term on the left side of the operator shall be a variable name, and the term on the right side of the operator shall be any expression. The result of the overall assignment expression shall be the result of the subexpression on the right hand side of the operator. ## Expression Separator Operator An **expr** expression can be separated into subexpressions by the semicolon \("**;**"\) character, which will have the same semantics as the "," operator in C. Thus, the return value of a call to **expr** is the value of the final subexpression, and the both sides of the expression shall be expressions. # Reference Implementation See <http://sourceforge.net/tracker/?func=detail&aid=1969722&group_id=10894&atid=310894> # Copyright This document has been placed in the public domain. |
Name change from tip/283.tip to tip/283.md.
|
| < | < | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | < > | | | | | < > | | | | | | | < > | | | | | | < > | | | | | < < > > | | | | | | | | | | | | | | | | | | | | < > | | < > | | | | | < > | | < | > | | | | | | | | | > | 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 | # TIP 283: Modify Ensemble Command Resolution Behaviour Author: Miguel Sofer <[email protected]> Author: Neil Madden <[email protected]> State: Draft Type: Project Vote: Pending Created: 01-Oct-2006 Post-History: Tcl-Version: 8.7 ----- # Abstract This TIP proposes that ensembles resolve all commands in their namespace. # Rationale Ensembles as proposed in [[112]](112.md) cannot interoperate with the **namespace path** and **namespace unknown** functionality: as they resolve all commands in the caller's scope, it is necessary to define them using fully qualified names to insure that they are found in the ensemble's namespace. But fully qualified names bypass the namespace's **path** and **unknown** redirectors. As an example \(and risking "uh-oo" reactions in the present context\) I would like to remark that this feature enables lightweight OO systems based on ensembles to provide inheritance of methods via **namespace path** and **namespace unknown**. # Proposed Change This TIP proposes to fix this by changing the man page description of the ensemble unknown handler from: > It is up to the unknown handler to supply all namespace qualifiers if the implementing subcommand is not in the namespace of the caller of the ensemble command. to: > The implementing subcommand is looked up in the ensemble's namespace using normal command location rules. The description of the _-map_ option should change from: > When non-empty, this option supplies a dictionary that provides a mapping from subcommand names to a list of prefix words to substitute in place of the ensemble command and subcommand words \(in a manner similar to an alias created with **interp alias**; the words are not reparsed after substitution\). to: > When non-empty, this option supplies a dictionary that provides a mapping from subcommand names to a list of prefix words to substitute in place of the ensemble command and subcommand words \(in a manner similar to an alias created with **interp alias**; the words are not reparsed after substitution\). The resulting command is invoked with the original arguments in the namespace of the ensemble, though no additional stack frames are pushed in the process. ## Compatability All scripts that followed previous best-practice and placed fully qualified command names in the command map or returned them from the unknown handler will be unaffected by this change. Only ensembles whose behaviour was undefined previously will be influenced, and then strictly in a positive direction. # Reference Implementation and Documentation [RFE 1577282] <http://sourceforge.net/tracker/index.php?func=detail&aid=1577282&group_id=10894&atid=360894> \(which depends on committed [Patch 1577278]\) provides an implementation, with tests and docs. # Illustration * Consider the following script \(without FQ names\) stored in /tmp/test: namespace eval a { proc check args {return YES} } namespace eval b { namespace path ::a namespace ensemble create \ -command ::b \ -map {go check} } namespace eval c { namespace path ::a namespace ensemble create \ -command ::c \ -map {go check} \ -unknown u proc u args {return check} } namespace eval d { namespace unknown u namespace ensemble create \ -command ::d \ -map {go check} proc u args {::a::check} } array set res {} foreach cmd {b c d} { foreach scmd {foo go} { catch {$cmd $scmd} msg set res($cmd|$scmd) $msg } } parray res Currently the output is mig@ice:~$ tclsh /tmp/test res(b|foo) = unknown or ambiguous subcommand "foo": must be go res(b|go) = invalid command name "::b::check" res(c|foo) = invalid command name "u" res(c|go) = invalid command name "::c::check" res(d|foo) = unknown or ambiguous subcommand "foo": must be go res(d|go) = invalid command name "::d::check" After this TIP, it should be mig@ice:~$ tclsh /tmp/test res(b|foo) = unknown or ambiguous subcommand "foo": must be go res(b|go) = YES res(c|foo) = YES res(c|go) = YES res(d|foo) = unknown or ambiguous subcommand "foo": must be go res(d|go) = YES * One commenter asked what the difference would be in the following code: namespace eval ens { proc foo {} { puts "Caller namespace is: [uplevel 1 namespace current]" puts "I am [namespace origin foo]" puts "I am called as: [lindex [info level 0] 0]" } namespace export ens namespace ensemble create -command ens -map {sub foo} } namespace eval caller { proc foo {} { puts "Caller namespace is: [uplevel 1 namespace current]" puts "I am [namespace origin foo]" puts "I am called as: [lindex [info level 0] 0]" } namespace import ::ens::ens ens sub } Today \(\*\) and after the patch this returns: Caller namespace is: ::caller I am ::ens::foo I am called as: ens \(\*\) Today==2006-24-10, after making **info level** aware of ensemble rewrites; prior to that date, only the last line would have changed from _::ens::foo_ to _foo_. # Remarks * See also [Bug 1436096] # Copyright This document has been placed in the public domain. |
Name change from tip/284.tip to tip/284.md.
|
| < | < | | | | | | | > | | | | | | | | | | | | | | | | | | | | | < > | | < > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 284: New 'invoke' and 'namespace invoke' Commands Author: Miguel Sofer <[email protected]> State: Draft Type: Project Vote: Pending Created: 01-Oct-2006 Post-History: Tcl-Version: 8.7 ----- # Abstract This TIP exposes a Tcl script-level interface to the direct command invokation engine already present in the Tcl library for years. # Proposed New Commands This TIP proposes a new subcommand to **namespace**, **invoke**, with the following syntax: > **namespace invoke** _namespace_ _cmd_ ?_arg_ ...? This invokes the command called **cmd** in the caller's scope, as resolved from namespace _namespace_, with the supplied arguments. If _namespace_ does not exist, the command returns an error. This TIP also proposes a new command: > **invoke** _level_ _cmd_ ?_arg_ ...? This invokes the command _cmd_ in level _level_ with the supplied _arg_uments. The syntax of _level_ is the same as that required by **uplevel**. # Rationale There is currently no script-level equivalent to _Tcl\_EvalObjv\(\)_, though the functionality is provided by one of: eval [list cmd ?arg ...?] {*}[list cmd ?arg ...?] Note that the core tries to optimise the first case, but has to be careful to only avoid reparsing when it is guaranteed safe to do so. The notation is rather clumsy too. The proposed new commands try to improve this situation, with the added functionality of determining the namespace in which the command name is to be resolved \(functionality which was very difficult to use previously using the script-level API\). In this manner it is possible for the invocation to make good use of **namespace path** and **namespace unknown** features. The new command **invoke** could be implemented as: proc invoke {level args} { if {[llength $args] == 0} { return -code error SomeMessage } if {[string is integer $level] && ($level >= 0)} { incr level } uplevel $level $args }] # Reference Implementation and Documentation [RFE 1577324] \(which depends on [Patch 1577278]\) provides an implementation of **namespace invoke**. <https://sourceforge.net/support/tracker.php?aid=1577324> <https://sourceforge.net/support/tracker.php?aid=1577278> # Differences to Other Commands 1. Both these commands perform command invocation, as opposed to the script evaluation done by **eval**, **uplevel**, **namespace eval** and **namespace inscope** 1. **namespace inscope** does a magic expansion of the first argument, **namespace invoke** takes the first argument as a command name. In other words, **namespace inscope** can be used with a command prefix. _Feedback on the semantics suggest that this is a worthy feature, very useful for packing up command prefixes. This tip may yet be revised or withdrawn to take that into consideration._ 1. Both **namespace eval** and **namespace inscope** add a call frame,**namespace invoke** does not - it invokes in the caller's frame. # Sample Usage In tcllib's **::math::calculus::romberg** we see \(edited for brevity\): # Replace f with a context-independent version set fqname [uplevel 1 [list namespace which [lindex $f 0]]] set f [lreplace $f 0 0 $fqname] ... set cmd $f lappend cmd [expr {0.5 * ($a + $b)}] set v [eval $cmd] where the command name in the prefix _f_ is replaced with its fully qualified name. A further variable is lappended, and the result is sent to **eval**. With **namespace invoke** and **invoke** this would be coded as: set ns [invoke 1 namespace current] set f [list namespace invoke $ns {*}$f] ... set v [{*}$f [expr {0.5 * ($a + $b)}]] If both new commands took the _cmd_ argument as a prefix to be expanded \(as suggested by some early commenters\), it would be even nicer for this usage: set ns [invoke 1 [list namespace current]] set f [list namespace invoke $ns $f] ... set v [invoke 0 $f [expr {0.5 * ($a + $b)}]] The same thing \(with slightly different semantics and a performance cost due to script evaluation instead of command invocation\) could be obtained today by doing: set f [uplevel 1 [list namespace code [list uplevel 1 $f]]] ... set v [eval [lappend f [expr {0.5 * ($a + $b)}]]] In order to fully reproduce the semantics and performance it would have to be: set f [uplevel 1 [list namespace code [list uplevel 1 $f]]] ... lset f end end [linsert [lindex $f end end] end [expr {0.5 * ($a + $b)}]] set v [eval $f] # Copyright This document has been placed in the public domain. |
Name change from tip/285.tip to tip/285.md.
|
| < | < | | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 285: Script Cancellation with [interp cancel] and Tcl_CancelEval Author: Joe Mistachkin <[email protected]> Author: Dawson Cowals <[email protected]> State: Final Type: Project Vote: Done Created: 04-Jun-2006 Post-History: Keywords: eval,cancel,unwind,terminate,runaway,async,thread,safe Tcl-Version: 8.6 ----- # Abstract This TIP introduces the ability to quickly and safely cancel a script within a specified interpreter from any thread in the process. # Key Use-Case Scenario When using Tcl inside a context such as a web-browser \(e.g. as a plugin\), it is often necessary for the execution of a particular script to be terminated cleanly without waiting for the script to get to a point where it is able to respond to events. For example, if the user encounters a page that contains a script that starts a long-running execution but then decides to navigate away from the page, it's important to stop the script as soon as possible. But we do not want to stop the script by means of just terminating the thread, as this can result in various resources being still allocated, as browsers are long-running applications. Some of the problems \(e.g. memory waste\) can be worked around by running the script in a separate process, but there are other resources that aren't cleaned up that way, such as locked files or shared memory blocks, and it is always better to give the Tcl interpreter itself an opportunity to clean up after itself. Furthermore, there are other possible applications \(such as using Tcl to implement COM objects on Windows\) where the separate-process method will not work so well. Instead, what is needed is a way to programmatically make a script stop its execution even when that script is otherwise determined to continue. This is different from a resource limit in that the cancellation is not caused by the exceeding of a predetermined value, but rather by some external event that is possibly even not processed initially by Tcl at all. # Technical Rationale Currently, once the evaluation of a script has been initiated it will do one of the following: * run to completion, * run until it encounters an uncaught error, * run until it exceeds a pre-determined limit as specified in [[143]](143.md), or * run indefinitely. In each of the cases above, neither the host application nor an interactive user have any recourse to terminate the script prior to it running its course. There are many situations for which it is absolutely necessary to be able to cancel a running script without its cooperation and without setting an arbitrary limit on the amount of time it can run \([[143]](143.md)\). This is especially true in a multi-threaded application embedding environment, or where a user interface is present. 1. In the case where the completion time for a script is unknown, non-existent, or non-deterministic a user may want or need to terminate the script prematurely. 2. When evaluating an untrusted - or marginally trusted - script in either a safe or standard interpreter, there is a risk that the script might never terminate. In such a situation it is not reasonable to forcibly terminate the thread or the entire process. > 1. Forcibly terminating a thread prevents Tcl and Tk from cleaning up their thread-specific memory and resources. > 2. The host application may suffer similar memory and resource leaks as well as other serious side-effects that may corrupt data, prevent other threads from properly synchronizing, or leave the process in an unknown and unrecoverable state. > 3. For an interactive host application valuable work may be lost without providing an opportunity to save pending modifications. Even in the absence of modifications the host application might have been holding locks that left unreleased would prevent other processes and users from using important resources. The basic building blocks needed for any scripting language to seamlessly integrate with an enterprise-ready host application are: * Engine Initialization * Evaluation * Extensibility * Cancellation * Engine Finalization Tcl now provides full support for all of the above except script cancellation. [[143]](143.md) allows for scripts to be prematurely terminated after reaching resource limits that were pre-arranged by the host application. However, this only handles terminating scripts based on a narrow set of deterministic criteria. Full support would require the ability to immediately and unconditionally terminate the evaluation of a script without adversely affecting the execution environment of the host application. In addition the following issues must be addressed: * Scripts being evaluated in nested slave interpreters. * Interaction with third-party extensions. * Safely usable by arbitrary threads. Several other mainstream scripting engines \(e.g., JavaScript, Microsoft Active Scripting, etc.\) currently provide this capability to cancel the evaluation of a script. This TIP proposes an implementation that would bring this necessary aspect of application integration to Tcl. This must be implemented in the core, because access to and modification of internal Tcl functions and data structures is required. # Specification A new **interp cancel** script command will be added, as follows: > **interp cancel** ?**-unwind**? ?**--**? ?_path_? ?_result_? This command cancels the script being evaluated in the interpreter. ## Arguments > **-unwind** This argument is optional. Without _-unwind_, the evaluation stack for the interpreter is unwound until an enclosing **catch** command is found or there are no further invocations of the interpreter left on the call-stack. With _-unwind_, the evaluation stack for the interpreter is unwound without regard to any intervening **catch** command until there are no further invocations of the interpreter left on the call-stack. > **--** This argument is optional, and marks the end of options. The argument following this one will be treated as being the _path_ argument even if it starts with a "-". > _path_ This argument is optional. If not supplied, the current interpreter is assumed; otherwise, the interpreter specified by _path_ is used. > _result_ This argument is optional. If not supplied, a default error message is left in the result of the interpreter; otherwise, the result specified by _result_ is used. ## Behavior When a script is canceled, the following occur: * The _CANCELED_ flag, and possibly the _TCL\_CANCEL\_UNWIND_ flag, are set in the interpreter to mark the evaluation in progress as having been canceled. * The currently executing command/script in the interpreter is made to return with code _TCL\_ERROR_. \(This is superior to using a novel return code, as third-party extensions are usually far better at handling error cases!\) * The **catch** command will only catch errors if the interpreter containing it does not have the _TCL\_CANCEL\_UNWIND_ flag set. * Additional trips through the internal loops of the **after**, **vwait**, **update** and **tkwait** commands will not proceed with the _CANCELED_ or _TCL\_CANCEL\_UNWIND_ flags set. \(Extensions can find this information out by using _Tcl\_Canceled_; see below.\) * Once the execution unwinds out of the interpreter, so that no further invocations of the interpreter are left on the call-stack, both of the script cancellation related flags are reset. * If there are no invocations of the interpreter on the call-stack when _Tcl\_CancelEval_ or **interp cancel** are called, then the next script to be evaluated will be preemptively canceled. ## Notes * Going forward, all "long running commands" in the Tcl/Tk core should make every effort to comply with the script cancellation functionality by calling _Tcl\_Canceled_ at times when it is appropriate to abort processing. * Extensions can optionally check if they should abort processing by calling _Tcl\_Canceled_. # C API ## Constants TCL\_CANCEL\_UNWIND: New eval-flag bit that applies to _Tcl\_CancelEval_ and _Tcl\_Canceled_. > When used in _flags_ for _Tcl\_CancelEval_, the evaluation stack for _interp_ is unwound without regard to any intervening **catch** command until there are no further invocations of _interp_ left on the call stack. When not set, the evaluation stack for the interpreter is unwound until an enclosing **catch** command is found or there are no further invocations of _interp_ left on the call-stack. > When used in _flags_ for _Tcl\_Canceled_, checks if the script being evaluated has been canceled using the _TCL\_CANCEL\_UNWIND_ flag \(i.e., the evaluation stack for _interp_ is being completely unwound\). TCL\_LEAVE\_ERR\_MSG: Existing variable-related flag bit that applies to _Tcl\_Canceled_ only. > When used in _flags_ for _Tcl\_Canceled_, an error message will be left in the result of _interp_ if the script being evaluated has been canceled. ## Functions > int **Tcl\_CancelEval**\(Tcl\_Interp \*_interp_, Tcl\_Obj \*_resultObjPtr_, ClientData _clientData_, int _flags_\) The **Tcl\_CancelEval** function initiates cancellation of the script being evaluated in _interp_. It returns a standard Tcl result. If _resultObjPtr_ is NULL, a default error message will be left in the result of _interp_ indicating that the script was canceled or unwound. If _resultObjPtr_ is not NULL, it will be used verbatim to supply the result of _interp_. The _clientData_ is reserved for future use and must be zero. This function may be called from any thread in the process, regardless of which thread created _interp_. > int **Tcl\_Canceled**\(Tcl\_Interp \*_interp_, int _flags_\) The **Tcl\_Canceled** function checks whether the script being evaluated in _interp_ has been canceled. Returns a standard Tcl result \(i.e., _TCL\_ERROR_ if the script being evaluated has been canceled\). This function should only be called from the thread which created _interp_; otherwise, its behavior is undefined. # Reference Implementation A reference implementation of this TIP is available <http://sf.net/tracker/?func=detail&aid=1499394&group_id=10894&atid=310894> . # Copyright This document has been placed in the public domain. |
Name change from tip/286.tip to tip/286.md.
|
| < | < | | | | | | | | > | | | | | | | | | | | | | | > | 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 | # TIP 286: Add 'xposition' Command to Menu Widgets Author: Schelte Bron <[email protected]> State: Final Type: Project Tcl-Version: 8.5 Vote: Done Created: 18-Oct-2006 Post-History: Keywords: Tk ----- # Abstract There has been a **yposition** subcommand for menu widgets for years, but its counterpart in the x-direction does not currently exist. This TIP intends to rectify that situation. # Rationale There is currently no way to obtain the x-position of a menu entry while a **menu** subcommand for obtaining the y-position does exist. Even though on a normal menu the x-position will always be 1, there are a few circumstances where the x-position may have some more interesting values. In particular, this is the case for menubars and for menus with column-breaks. # Proposed New Command This TIP proposes a new subcommand for **menu** widgets, **xposition**, with the following syntax: > _pathName_ **xposition** _index_ This returns an integer giving the x-coordinate within \(i.e., relative to\) the menu window specified by _pathName_ of the leftmost pixel in the entry specified by _index_. The _index_ may take any of the normal forms for identifying a menu entry. # Reference Implementation Submitted to SourceForge as Patch \#1152376. <http://sf.net/tracker/?func=detail&aid=1152376&group_id=12997&atid=312997> # Copyright This document has been placed in the public domain. |
Name change from tip/287.tip to tip/287.md.
|
| < | < | | | | | | | | > | | | | | | | | | | | < > | | | | | | | | | | | | | | | | | | < | > | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 287: Add a Commands for Determining Size of Buffered Data Author: Michael A. Cleverly <[email protected]> State: Final Type: Project Vote: Done Created: 26-Oct-2006 Post-History: Keywords: Tcl,channel,chan,pendinginput,pendingoutput Tcl-Version: 8.5 ----- # Abstract Many network servers programmed in Tcl \(including the venerable tclhttpd\) are vulnerable to DoS \(denial of service\) attacks because they lack any way to introspect the amount of buffered data on a non-blocking socket that is in line buffering mode. This TIP proposes a new subcommand to **chan** to allow the amount of buffered input and buffered output \(for symmetry\) to be inspected from Tcl. # Rationale Many network protocols are inherently line-oriented \(HTTP, SMTP, etc.\) and the natural approach to implementing servers for these protocols in Tcl is to configure the incoming client sockets to use non-blocking I/O and to have _line_ buffering and then define a readable fileevent callback. proc accept {sock addr port} { fconfigure $sock -buffering line -blocking 0 fileevent $sock readable [list callback $sock ...] } socket -server accept $listenPort Recall that a readable fileevent will be called even when there is an incomplete line buffered. As the **fileevent** manual page states: > A channel is considered to be readable if there is unread data available on the underlying device. A channel is also considered to be readable if there is unread data in an input buffer, except in the special case where the most recent attempt to read from the channel was a gets call that could not find a complete line in the input buffer. The **fblocked** \(and in 8.5 **chan blocked**\) command provides the Tcl programmer a means to test whether: > the most recent input operation ... returned less information than requested because all available input was exhausted. There is currently no way at the Tcl level to see how much data is buffered and could be read safely \(via **read** instead of **gets**\). There is also no way to specify any kind of upper limit on the length of a line; when in line-buffering mode all input is buffered until an end-of-line sequence is encountered or the EOF on the channel is reached. The practical result is that all network daemons written in Tcl using line-oriented I/O \(**gets**\) can be fed repeated input lacking an end-of-line sequence until all physical memory is exhausted. This vulnerability has been recognized since at least 2001. See, for example, the discussion between George Peter Staplin and Donald Porter on the _gets_ page on the Tcl'ers Wiki <http://wiki.tcl.tk/gets> . # Proposed Change At the C level Tcl already has a function, _Tcl\_InputBuffered_ which returns the number of unread bytes buffered for a channel and a corresponding _Tcl\_OutputBuffered_ which returns the number of bytes buffered for output that have not yet been flushed out. This TIP proposes to implement a new _chan pending_ command which will take two arguments: a _mode_ and a _channelId_. The mode argument can be either _input_ or _output_. When the mode is _input_ the command returns the value of _Tcl\_InputBuffered\(\)_ \(if the channel was open for input or -1 otherwise\). When the mode is _output_ the command returns the value of _Tcl\_OutputBuffered\(\)_ \(if the channel was output for output or -1 otherwise\). This allows a programmer developing network daemons at the Tcl level to implement their own policy decisions based on the size of the unread line. Potential DoS situations could be avoided \(in an application specific manner\) long before all memory was exhausted. if {[chan blocked $sock] && [chan pending input $sock] > $limit} { # Take application specific steps (i.e., [close $sock] or # [read $sock] to process a partial line and drain the buffer, etc.) } # Rejected Alternatives * Adding a flag to **fblocked** to return the number of unread bytes instead of just 0 or 1 \(since **fblocked** is now considered deprecated as per [[208]](208.md)\). * Polluting the global namespace with a new **favailable**, **fpending** or **fqueued** command. * A **chan unread** because of potential confusion as to whether it performed _ungetch\(\)_ type functionality \(_un-reed_ vs _un-red_\). * Any sort of **-maxchars** or **-maxbytes** flag to **gets** in order to not complicate the semantics of **gets**. Additionally without even further complicating **gets** semantics one could not distinguish input of exactly $limit characters from the case where only $limit characters were returned \(with some input remaining unread\). * The initial version of this TIP called for a _chan available_ command. This was changed to _pendinginput_ \(and _pendingoutput_ added for symmetry's sake\) following suggestions on news:comp.lang.tcl from Donald Arseneau and Donal Fellows, and later to _chan pending_ that takes a _mode_ argument \(_input_ or _output_\) based on suggestions from Donald Porter and Joe English. # Reference Implementation [RFE 1586860] at SourceForge now contains a patch implementing **chan pendinginput** and **chan pendingoutput** \(including updated **chan** man page and corresponding test cases\) <http://sourceforge.net/tracker/index.php?func=detail&aid=1586860&group_id=10894&atid=360894> . # Copyright This document is in the public domain. |
Name change from tip/288.tip to tip/288.md.
|
| < | < | | | | | | | | | | > | | | | | | | | | | | | | < > | < > | | | < > | | | | | | | < > | < | > | | | | | | | | | > | 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 | # TIP 288: Allow "args" Anywhere in Procedure Formal Arguments Author: Peter Spjuth <[email protected]> Author: Andreas Leitgeb <[email protected]> Author: Peter Spjuth <[email protected]> State: Draft Type: Project Vote: Pending Created: 03-Oct-2006 Post-History: Keywords: Tcl,proc Tcl-Version: 8.7 ----- # Abstract This TIP proposes to make _args_ have its special meaning as a formal **proc**edure argument anywhere in the argument list. # Rationale Many commands, specially many of Tcl's built in commands, have their variadic arguments in the beginning of the argument list and their required arguments at the end. An example is [**lsearch** ?_options_? _list string_]. Writing tcl procedures in that style is currently a bit cumbersome since you need to do you own argument counting and assignment to variables from "args". If "args" had its special meaning at any location in the argument list, it would help with such a task, and it would make things more consistent. To get simple semantics, optional arguments are not allowed after "args". Optional arguments that precede "args" will be handled as before. This TIP does not, as of now, specify defaulted arguments directly preceding non-defaulte ones. This should be addressed in a separate TIP. # Specification At most one proc argument may be named "args" and can be anywhere in the argument list. Arguments after "args" may not be optional. Arguments are assigned in the following order: 1. Assign arguments right of "args" from the right. 2. Assign arguments left of "args" from the left. Handling of defaulted parameters preceding "args" remains as it was \(but disregarding the non-defaulted ones after "args"\). 3. Remaining arguments are assigned to "args". # Compatiblity Currently "args" is allowed anywhere in the argument list, and becomes a normal variable if not last. Most scripts probably don't use this since it would be rather confusing, but it might exist. All such occurrances would need to be fixed. Detecting such scripts in an automated way would be simple and fixing them is trivial. # Examples New style: proc lgurka {args list item} { array set opts {-apa 1 -bepa "" -cepa 0} foreach {arg val} $args { set opts([prefix match {-apa -bepa -cepa} $arg]) $val } # Do real stuff } Old style: proc lgurka {args} { if {[llength $args] < 2} { return -code error "wrong # args: should be \"lgurka ?args? list item\"" } set item [lindex $args end] set list [lindex $args end-1] set args [lrange $args 0 end-2] array set opts {-apa 1 -bepa "" -cepa 0} foreach {arg val} $args { set opts([prefix match {-apa -bepa -cepa} $arg]) $val } # Do real stuff } proc x {a args b} { puts "a=$a, args=$args, b=$b" } x 1 2 ;# -> a=1, args=, b=2 x 1 2 3 ;# -> a=1, args=2, b=3 x 1 ;# -> error: wrong # args: should be "x a ?args? b" proc y {a {b x} args c} { ... } y 1 2 3 ;# a=1 b=2 c=3 args is empty proc z {a {b x} c args} { ... } z 1 2 ;# -> error: wrong # args: should be "z a ?b? c ..." To change "z" is not covered by this TIP. # Copyright This document has been placed in the public domain. |
Name change from tip/289.tip to tip/289.md.
|
| < | < | | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 289: Revision of [lrepeat] Argument Order Author: Peter Spjuth <[email protected]> Author: <[email protected]> State: Rejected Type: Project Vote: Done Created: 26-Oct-2006 Post-History: Keywords: Tcl Tcl-Version: 8.5 ----- # Abstract This TIP proposes to alter the argument order of **lrepeat** to be similar to **string repeat**. # Rationale In [[136]](136.md), lrepeat is defined as: > **lrepeat** _number element1_ ?_element2_? ?_element3_? ... whereas the old string repeat command is: > **string repeat** _string number_ This difference between similar commands is bound to cause confusion. Consistency is good. # Specification Change lrepeat's argument order to: > **lrepeat** _element1_ ?_element2_? ?_element3_? ... **number** # Examples: lrepeat 0 100 - returns list of 100 zeros lrepeat [lrepeat 0 100] 100 - returns 100x100 matrix (list of lists) of zeros lrepeat a b c 3 - returns nine-element list {a b c a b c a b c} lrepeat a b c 1 - identical to [list a b c] # Discussion: DGP: The main feature that appears to get lost in this change is the ability to redirect aliases or subcommands of ensembles to **lrepeat** calls with the number of repetitions already filled in. PS: On the other hand, you get the ability to redirect aliases or subcommands of ensembles to **lrepeat** calls with the elements already filled in. DGP: I skimmed the old TIP 136 messages in the TCLCORE archives. One thing to note is that the existing **lrepeat** syntax in 8.5a5 was chosen in part to be consistent with the existing **struct::list repeat** syntax in the struct::list package. DGP: I think it's fair to say that given a complete "do-over" more of us would opt to change **string repeat** to agree with **lrepeat** and **struct::list repeat** than the other way around. # Copyright This document has been placed in the public domain. |
Name change from tip/29.tip to tip/29.md.
|
| < | < | | | | | | | | | > | | | | | | | | | | | | | | < > | < | > | | | | | | | | | | | | | | | | | | < > | < | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | < > | < > | | | | | < > | | | | | | < > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 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 | # TIP 29: Allow array syntax for Tcl lists Author: Kevin Kenny <[email protected]> Author: Donal K. Fellows <[email protected]> State: Rejected Type: Project Vote: Done Created: 07-Mar-2001 Post-History: Discussions-To: news:comp.lang.tcl,mailto:[email protected] Tcl-Version: 9.0 ----- # Abstract Most popular programming languages provide some sort of indexed array construct, where array subscripts are integers. Tcl's lists are, in fact, arrays, but the existing syntax obscures the fact. Moreover, the existing list commands make it difficult to manipulate lists as arrays without running into peculiar performance issues. This TIP proposes that the syntax of _variableName\(value\)_ be extended to function as an array selector if _variableName_ designates a list. This change is upward compatible with existing Tcl scripts, because the proposed syntax results in a runtime error in every extant Tcl release. # Rationale The implementation of lists in Tcl has evolved far beyond the original conception. While lists were originally conceived to be strings with a particular syntax that allowed them to be parsed as lists, the internal representation of a list is now an array of pointers to _Tcl\_Obj_ structures. Tcl programmers, for the most part, have not taken advantage of this evolution. Code that uses hash tables for the purpose is still extremely common. Moreover, it is difficult to update lists in place, even if their internal representations are known not to be shared. One example of this difficulty is seen in the discussions <http://purl.org/thecliff/tcl/wiki/941> of how best to shuffle a list of items. The discussion began with a naïve implementation of Jon Bentley's method of performing random swaps: proc shuffle1 { list } { set n [llength $list] for { set i 0 } { $i < $n } { incr i } { set j [expr {int(rand()*$n)}] set temp [lindex $list $j] set list [lreplace $list $j $j [lindex $list $i]] set list [lreplace $list $i $i $temp] } return $list } Aside from the fact that the syntax obscures what the program is doing, the implementation suffers from an obscure performance problem. When the _lreplace_ calls in the _shuffle1_ procedure are executed, the internal representation of _list_ has two references: the value of the variable, and the parameter passed to _lreplace_. The multiple references force _lreplace_ to copy the list, leading to quadratic performance when large lists are shuffled. It is possible, albeit difficult, to alleviate this problem by careful management of the lifetime of _Tcl\_Obj_ structures, but this change complicates the code. The simplest way to fix the performance is probably to use Donal Fellows's implementation of the _K_ combinator: proc K { x y } { set x } which allows the caller of _lreplace_ to extract the value of _list_, change the value of _list_ so that the extracted value is unshared, and then pass the extracted value as a parameter to _lreplace:_ proc shuffle1a { list } { set n [llength $list] for { set i 0 } { $i < $n } { incr i } { set j [expr {int(rand()*$n)}] set temp1 [lindex $list $j] set temp2 [lindex $list $i] set list [lreplace [K $list [set list {}]] $j $j $temp2] set list [lreplace [K $list [set list {}]] $i $i $temp1] } return $list } Now the performance of the code is _O\(n\)_ where _n_ is the length of the list, but the programmer's intent has been seriously obscured! These drawbacks have led prominent individuals such as Richard Stallman <http://www.vanderburg.org/Tcl/war/0000.html> to assert that Tcl lacks arrays. _This proposal includes the absolute minimum of functionality needed to provide array-style indexing for variables containing Tcl list objects._ The reason for this limitation is that omitted functionality can be added later without breaking existing scripts. On the other hand, ill-considered extensions may turn into something that we're doomed to support forever. # Specification This TIP's proposed change can be stated succinctly: > Wherever the notation _a\(x\)_ may be used to refer to an array element in the language, allow it also to refer to an element of a list, provided that the variable _a_ is scalar and the value _x_ is an index suitable for the _lindex_ command. _Exception:_ Traces, _unset_ and _upvar_ calls designating individual list elements shall not be supported. \(As a consequence of this rule, list elements may also not appear as linked variables in C code, implying that they also cannot appear as _-variable_ or _-textvariable_ options on Tk widgets.\) Note that this change is backward compatible with existing Tcl scripts! If a notation like _a\(x\)_ is used to refer to a scalar variable in today's Tcl, the result is an error: % set a [list foo bar grill] foo bar grill % set a(2) can't read "a(2)": variable isn't array % puts $a(2) can't read "a(2)": variable isn't array % set a(2) zot can't set "a(2)": variable isn't array The default behavior, if _a_ is not set, and a script executes set a(2) zot will still be to create an associative array. If a script wishes to perform such actions on a list, it will be necessary first to initialize the variable: set a [list] set a(0) foo Note that in the example above, there is no requirement that the internal representation of _a_ be a list; the line, set a [list] could have been replaced with set a {} with the only impact being the run-time cost of shimmering the empty string into an empty list. Nowhere does this proposal introduce behavior that depends on a specific internal representation for any variable. This proposal the syntax of the subscript shall be precisely those values that are accepted as the second argument to the _lindex_ command. In other words, the subscript may be an integer _N_, or the string _end_ or _end-N_. The value of _N_ may not be less than zero nor greater than nor equal to the length of the list on any usage that reads a list element. A usage that writes a list element may use an integer equal to the length of the list, or the string _end\+1_, to designate the element one past the end. In other words, set a(end+1) foo will have the same effect as: lappend a foo With the proposed change in syntax, the procedure to shuffle a list becomes much more straightforward: proc shuffle1 { list } { set n [llength $list] for { set i 0 } { $i < $n } { incr i } { set j [expr {int(rand()*$n)}] set temp $list($j) set list($j) $list($i) set list($i) $temp } return $list } The given implementation copies the list only once, the first time that the line: set list($j) $list($i) is executed. Thereafter, the list is an unshared object, and the replacements are performed in place. It shall be illegal to pass a list element as the parameter to _upvar;_ that is, the following usage: proc increment { varName } { upvar 1 $varName v incr v } set x [list 1 2 3] increment x(0) will _not_ be supported. However, the commoner form: proc incrementElement { arrayName index } { upvar 1 $arrayName array incr array($index) } set x [list 1 2 3] incrementElement x 0 will, of course, work as expected. # Discussion Several reviewers expressed concern about the reuse of array syntax. In particular, the alternative syntax $a<$element> was proposed repeatedly. Alas, there is no good alternative syntax that will not break at least some existing scripts. The proposed syntax using angle-brackets is a poor choice, because Tcl scripts that generate Web pages frequently have code like: puts "<$tag>$text</$tag> that would be broken horribly by such a change. There are several obvious extensions to the proposal that are not addressed, and these omissions are intentional. * The proposal makes no attempt to deal with multiple subscripts as a means of accessing nested lists. Use of multiple subscripts is closely related to the withdrawn [[22]](22.md) \(which the author of this TIP intends to revive\). If the related TIP is accepted, the syntax for the subscript could readily be expanded so that it could be a Tcl list giving the subscripts in lexicographic sequence. For example set a(2 3) foo could be used to set the fourth element of the third sublist. * The proposal allows the _set_ command \(or any other use of _Tcl\_SetVar2Ex_\) to set only the elements that are in the list already plus the one one beyond the end. Tcl lists are fundamentally dense arrays. Allowing non-contiguous elements, that is, sparse arrays, is a fundamental change to their semantics. Such a change is not contemplated at this time. * The proposal does not allow the _unset_ command \(or any other command that arrives at _Tcl\_UnsetVar2_\) to delete members of a list. Earlier versions of the proposal had proposed to permit: unset a([expr { [llength $a] - 1}]) or equivalently: unset a(end) to reduce the length of the list by one. In subsequent discussions, the reviewers found it distasteful that the proposed syntax did not permit unsetting interior elements of a list. Alas, the discussion did not arrive at a consensus on what the precise semantics of such an operation ought to be. Some reviewers favored attempting to emulate sparse arrays \(again, a fundamental change to the semantics of Tcl lists that is not contemplated at this time\). Others preferred the semantics of shifting the remaining elements, so that unset a($n) would always be equivalent to set a [lreplace $a $n $n] except for performance. Both camps found it overly restrictive to limit the semantics of _unset_ to those of the original proposal. Because the two groups failed to achieve a consensus, the author of this TIP finds it prudent to forbid _unset_ altogether in the initial implementation. * The _array_ command continues to operate only on associative arrays. Lists are a simple enough structure that the full power of the _array_ command is not required to deal with them, and having it work on lists as well as arrays seems like needless effort. Moreover, existing code may well depend on a combination of _[array exists]_ and _[info exists]_ to distinguish associative arrays from scalar variables \(including lists\). * The _upvar_ command cannot address individual list elements. Extending the syntax in this fashion would make _upvar_ more consistent in its behavior, but appears to be expensive, in terms of both performance \(tracking down the linked references if a list is rebuilt\) and the effort required for implementation \(the author of this TIP is unlikely to have the time required to implement the necessary changes to _struct Var_ and the associated code\). * No traces on list elements shall be supported. List elements cannot function as linked variables in C code. The original proposal had specified how write and unset, but not read, traces could be implemented. The original proposed functionality is described in the Appendix. The author of this TIP had proposed it primarily so that list elements could function as linked variables \(for instance, in the _-variable_ and _-textvariable_ options of Tk widgets\). Once again, this part of the original proposal failed for lack of consensus among the reviewers. Some felt that supporting read traces in one context but not another would be overly confusing. Moreover, the proposal as written would cause write traces on the elements to fire if the internal representation of a variable shimmered between a list and something else. Some reviewers found the excess trace callbacks to be objectionable. At least one reviewer proposed a separate _trace add element_ syntax for list-element traces. This syntax would address some of the concerns about the lack of read traces \(there's no reason that _trace add element_ should function the same as _trace add variable_\). Alas, it would not address the problem of linked variables, which was the main reason for having the traces in the first place. Given the lack of consensus, the author of this TIP finds it prudent to withdraw or postpone this portion of the proposal. # See Also [[22]](22.md) - withdrawn. # Reference Implementation No reference implementation has yet been developed; the author of this TIP wishes to solicit the opinions of the Tcl community before spending a lot of time implementing a possibly bad idea. # Change history _12 March 2001:_ Added detailed discussion of the specific subscript ranges supported by read, write and unset operations. Changed the discussion to reject the alternative of padding an array when setting an index beyond the end. Added discussion of the details of write and unset traces, and rejecting read traces as being infeasible to implement. Clarified the example of creating an empty list so as to avoid any misapprehension that these changes depend on list variables' having a particular representation at any given time; in fact, every detail of this proposal is tolerant of shimmering. _13 March 2001:_ Fixed a copy-and-paste error in the 'incrementElement' example, and added to the discussion the fact that all operations will throw errors in the event of a malformed list. _30 March 2001:_ Revised yet again, in an attempt to remove as much controversial functionality as possible and reduce the TIP to the minimum useful subset, on the grounds that it is prudent to avoid supporting functionality that may later prove ill-considered. # Summary of objections _DeJong,_ _English_ \(non-voting\), _Flynt_ \(non-voting\), _Harrison,_ _Ingham,_ _Lehenbauer,_ _Polster,_ \(non-voting\), _Porter,_ and _Sofer_ \(non-voting\), expressed concern that the proposed syntax is confusing, since the target object could be either an associative array or a linear array \(that is, a Tcl list\). These objections varied in stridency from "yes, it is a risk, and I'm prepared to accept it," to "this will just be too confusing, and I can't countenance this proposal." _Hobbs_ found the original proposal's omission of reverse indexing distasteful. The current version of the proposal embraces his suggested change. _Cuthbert_ \(non-voting\), _Hobbs_, and _Porter_ expressed concern over the semantics of _unset._ Since consensus was not achieved, the current version of the proposal defers implementation of _unset._ Several reviewers, most notably _Ousterhout,_ found the proposed _trace_ semantics distasteful. The current version of the proposal eliminates _trace_ on list elements. Several reviewers appeared to labor under the misconception that this TIP introduces behavior that is dependent at run time upon the internal representation of a Tcl object. It does not; it is tolerant of shimmering in all cases. Several reviewers objected to the proposal on the grounds that it does not specify a general object system and how such a system would allow for generic containers with array syntax. The author's intention in writing it was not to propose such a system, but only to propose a small piece of syntactic sugar, implementable here and now, that is compatible with that broader vision. # Appendix: Possible implementation of read and unset traces. The original proposal contained the following language, which could be used as a guide if traces on list elements are contemplated at a future time. Write and unset traces on list elements shall be supported; it shall be permissible to write: trace add variable x(1) write writeCallback or trace add variable x(1) unset unsetCallback The _write_ callback shall be invoked whenever the given list element changes value; the _unset_ callback shall be invoked whenever the variable is unset or when its length shrinks to the point that it no longer has a member with the given index. Read traces on list elements shall _not_ be supported. It is too difficult at this point to define what their semantics should be. For instance, if a program executes the following code: trace add variable x(0) read readCallback set x [list foo bar grill] set y [string range $x 4 end] should the callback fire? By one argument, the program has not read element zero of the list; by another, using the list as a string has read every element, and all read traces should fire. In any case, the read trace on a variable fires before its usage is known; it appears impossible in existing code to implement selective read tracing on list elements. The implementation of write and unset traces on list elements will be done by establishing a C-level write trace on the variable as a whole. The client data of the trace will designate a structure containing the ordinal number of the element being traced, and a _Tcl\_Obj_ pointer designating its old value. The reference count of the _Tcl\_Obj_ will be incremented when this pointer is stored. Note that this increment operation makes the object shared. Any change to the designated element will thus need to copy the object. When the write trace fires, the list representation of the variable will be extracted, reconstituting it from the string representation if necessary. If extracting the list representation fails, the trace will be considered to have failed as well, and the trace callback will return _TCL\_ERROR_. If extracting the list representation succeeds, the list length will be compared with the ordinal number of the element being traced. If the element number is no longer within the list, an unset trace fires if one exists. If the element number is within the list, the two _Tcl\_Obj_ pointers are compared. If they are identical, the list element in question is unchanged, and nothing need be done. Otherwise, the write trace fires. This behavior is conservative in that an operation that spoils the list representation of the object is considered to have written every element of the list. This rule is consistent with the rule that write traces on ordinary Tcl variables fire whenever the variable is set, even if it is being set to an identical value. In any event, after the conclusion of a trace callback, the saved Tcl\_Obj will have its reference count decremented and be replaced with the current element of the list \(with reference count appropriately incremented, of course\). # Copyright This document has been placed in the public domain. |
Name change from tip/290.tip to tip/290.md.
|
| < | < | | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | < < > > | | | < > | | | | < > | | | | | | | | | | | | | | | | | | | < > | | | | < < < | > > > | | | | | | > | 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 | # TIP 290: Registration of Custom Error Handler Scripts Author: Eckhard Lehmann <[email protected]> Author: Larry W. Virden <[email protected]> State: Draft Type: Project Vote: Pending Created: 29-Oct-2006 Post-History: Keywords: Tcl,error,trap Tcl-Version: 8.7 ----- # Abstract This TIP proposes the possibility to register a custom command as error and exception handler. # Rationale Errors are thrown in the Tcl interpreter through the **error** command or from a C extension that returns TCL\_ERROR. When an error is thrown, the global _errorInfo_ variable is filled with rudimentary stacktrace information and the error message itself. The global _errorCode_ variable can contain an error code if this is provided by the command that has thrown the error. Errors can be caught with the **catch** command. In this case, the _errorInfo_ variable is still filled with the information mentioned above, but the error is not presented to the interpreter. If the error is not caught, it is presented to the interpreter and the execution of the current code is aborted immediately The information in _errorInfo_ is, in some simple cases, useful for reproducing and tracking down the error source and fixing the problem. In more complicated cases however, _errorInfo_ does not include enough information to successfully reproduce the error - information about the application's state is missing. In other languages such as LISP, this problem is addressed by stopping the execution at the position where the error was thrown \(preserving the current callframe\) and presenting the developer with a console that enables him to introspect the running program. Although Tcl has very good introspection capabilities, it is not possible to use them in an error case, because the execution just aborts and the stacktrace is unwound at once. For errors generated with the **error** command, it is possible to overwrite this command and provide more advanced functionality, but this is not possible if errors are generated in C code by _return TCL\_ERROR_. The proposed implementation addresses this problem by a custom error command that is executed whenever an error occurs in the execution of Tcl code. This opens a range of implementation possibilities for error handling, for instance: * registering a _breakpoint_ command that stops execution at the error position and opens a console for introspection * registering a more advanced \(Tk\) debugger that opens on error for introspection. * registering a command that captures the state of each call-frame up to the one where the error was thrown and writes that state to a file. This file can later be debugged \(with an appropriate tool\). # Alternatives 1. Overwriting of the **error** command As stated abovem, this works only for errors generated from Tcl code, whereas it does not work for errors from C extensions. 2. Leavestep execution traces In Tcl >=8.4 it is possible to register execution traces on _leavestep_ to commands. To implement part of the proposed functionality it would be possible to add a leavestep trace procedure, which - after each command - checks for the return code and acts accordingly. The problem with this approach is, that the procedure is called after _each_ command, independent from whether it returned an error or not. This can slow down the program execution more or less significantly. Furthermore, it is not easy if at all possible to capture occurences of **catch** by this way, so it is complicated or impossible to react on caught errors. It might be possible to get part or most of the proposed functionality by _trace add execution leavestep_ or overwriting of **error**. But it is the responsibility of the core language \(even more when it is a dynamic language\) to provide customizable and advanced error handling. The TIP proposes in this direction. # Specification The implementation consists of two parts: a registration command for the custom command and a place where the handler is called. For this to work, there are some minor changes necessary to the Tcl execution engine and to the Interp structure. For running the handler on caught and or uncaught errors \(depending on how the user wants to have it\) it is necessary to capture the current level of "catch"es that occure during execution. The registration command is responsible for: * register the command for caught and/or uncaught exceptions * retrieve the currently registered command * change the execution details \(caught and/or uncaught errors\) and the command * unregister the command and thus get back to the current behaviour in error cases Since the functionality is very similar to the family of **trace** commands, the proposed registration command is an extension to trace: **trace set exception ?-caught? ?-uncaught? ?command?**: Registration and modification The arguments _-caught_ and/or _-uncaught_ to _trace set exception_ modify the run conditions for the currently registered handler \(run on caught/uncaught errors\). With the _command_ argument, this is set as the new handler. The return code and result of the command that was executing is appended to the registered _command_. So, the real call is: _command code result_. **trace info exception**: Information about the current handler This command returns a list with the elements \{-caught y/n -uncaught y/n script\}, where caught and uncaught flags are specified and script is the currently registered handler. **trace unset exception**: Remove registerred handler Any previously set error handler is unregistered. The _command_ that is registered will quell the error if it returns normal \(return code 0\). If the script returns abnormal, it's return code is returned to the interpreter. Errors inside the handler are not trapped by the script again, rather they are presented to the interpreter as usual - otherwise this would result in an endless loop. The changes in the execution engine should be done so that: * existing functionality is not disturbed * the call frame is preserved after the error occured - thus the custom command is run in the same level as where the error was thrown * the _::errorInfo_ and _::errorCode_ variables are updated to contain the error information **that is available in the current callframe**. This information must be updated before the custom command is run, so that it is accessible from there. The innermost function that is called on Tcl code execution is _TclEvalObjvInternal\(\)_. It is called from others to execute a command and returns the code that the executed command returned. It's the best place to trigger the error handler execution, but whether errors are catched \(catchLevel\) must be present at this time. Therefore, this level is stored in the current Interp\* from within the callers of _TclEvalObjvInternal\(\)_. The catch level can be determined either from _TclExecuteByteCode\(\)_ or from _Tcl\_CatchObjCmd\(\)_ directly. The errorInfo and errorCode variables are set directly before the handler is run. This ensures that they are updated properly. Eventually registerred traces on this variable are handled as usual, before the custom error command is executed. # Reference Implementation A reference implementation is available from sourceforge as a patch against Tcl 8.5a5 <http://sourceforge.net/support/tracker.php?aid=1587317> . # Usage Example Here is a sample procedure that can be used to stop execution on error \(return code 1\) and introspect the program using stdin/stdout. Other return codes are returned together with the previous result. The procedure was mainly implemented by Neil Madden as **debug-repl** and is available \(with a short discussion on the topic\) on <http://lambda-the-ultimate.org/node/1544#comment-18446> : package provide debug 1.0 proc up {} { uplevel 2 { breakpoint } } proc down {} { return -code continue } proc breakpoint {code result} { if {$code > 1} { return -code $code $result } set cmd "" set level [expr {[info level]-1}] set prompt "Debug ($level) % " while {1} { puts -nonewline $prompt flush stdout gets stdin line append cmd $line\n if {[info complete $cmd]} { set code [catch {uplevel #$level $cmd} result] if {$code == 0 && [string length $result]} { puts stdout $result } elseif {$code == 3} { break } elseif {$code == 4} { # continue return } else { puts stderr $result } set prompt "Debug ($level) % " set cmd "" } else { set prompt " " } } } To use it for uncaught errors, the _breakpoint_ procedure can be registered as error command: package re debug trace set exception -uncaught breakpoint When an error raises, _breakpoint_ is called in the current callframe and Tcl introspection commands like **info vars** etc. can be used to get information about the program state. # Copyright This document has been placed in the public domain. |
Name change from tip/291.tip to tip/291.md.
|
| < | < | | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 291: Add the 'platform' Package to Tcl Author: Steve Landers <[email protected]> Author: Andreas Kupries <[email protected]> State: Final Type: Project Vote: Done Created: 26-Oct-2006 Post-History: Keywords: Tcl,Critcl,TEApot Tcl-Version: 8.5 ----- # Abstract This TIP proposes adding the **platform** package to the Tcl core sources and to install it automatically, similar to what is currently done with the **tcltest** package. # Rationale It has been shown by the current users of the **platform** package - the **Critcl** \(C Runtime in Tcl\) and the **TEApot** repository system - that it is useful to not only be able to identify the architecture of a machine running Tcl, but to condense this information into a single identifier, standardized across platforms. Whilst Tcl provides the _tcl\_platform_ array for identifying the current architecture \(in particular, the platform and machine elements\) this is not always sufficient. This is because \(on Unix machines\) _tcl\_platform_ reflects the values returned by the **uname** command and these aren't standardized across platforms and architectures. In addition, on at least one platform \(AIX\) the _tcl\_platform\(machine\)_ contains the CPU serial number. Consequently, individual applications need to manipulate the values in _tcl\_platform_ \(along with the output of system specific utilities\) - which is both inconvenient for developers, and introduces the potential for inconsistencies in identifying architectures and in naming conventions. Placing the **platform** package into the core in the same manner as **tcltest** will prevent such fragmentation - i.e., it will establish a standard naming convention for architectures running Tcl - and will make it more convenient for developers to identify the current architecture a Tcl program is running on. # Specification of the proposed Change ## Tcl Level API Two new packages, **platform** and **platform::shell** are made available, and can be loaded into Tcl via **package require**. The package **platform** provides three commands: 1. **::platform::identify** > This command returns an identifier describing the platform the Tcl core is running on. 1. **::platform::generic** > This command returns a simplified identifier, leaving out details like kernel version, libc version, etc. 1. **::platform::patterns** _id_ > This command takes an identifier as returned by **::platform::identify** and returns a list of identifiers for compatible architectures. All identifiers have the general format _OS_-_CPU_. The CPU part will not contain dashes anymore, whereas the OS part may contain dashes. The package **platform::shell** provides three commands as well, two of which are wrappers around commands provided by **platform**. 1. **::platform::shell::generic** _shell_ > This command returns the generic identification of the specified _shell_. The shell has to be executable on the host machine, but does not have to have the package **platform** itself. This is supplied by the caller. 1. **::platform::shell::identify** _shell_ > This command returns the exact identification of the specified _shell_. The shell has to be executable on the host machine, but does not have to have the package **platform** itself. This is supplied by the caller. 1. **::platform::shell::platform** _shell_ > This command returns the contents of _tcl\_platform\(platform\)_ for the specified _shell_. The shell has to be executable on the host machine. ## Public C API One deficiency in the current implementation of the package _platform_ is the difficulty of distinguishing 64bit and 32bit systems. To remove this deficiency the variable _tcl\_platform_ of the Tcl core is extended to contain an entry _pointerSize_. The value associated with this entry is the number of bytes needed by the machine to store a _void \*_ pointer. # Discussion When choosing the format for platform identifiers we had two contenders, i.e. _OS_-_CPU_ vs. _CPU_-_OS_, the second of which is used by GCC. However for developers using a scripting language like Tcl the OS is of more importance than the CPU architecture. Because of this the first form was chosen. # Reference Implementation This is available on SourceForge <http://sourceforge.net/support/tracker.php?aid=1600701> . # Copyright This document has been placed in the public domain. Please note that any correspondence to the author concerning this TIP is considered in the public domain unless otherwise specifically requested by the individual\(s\) authoring said correspondence. This is to allow information about the TIP to be placed in a public forum for discussion. |
Name change from tip/292.tip to tip/292.md.
|
| < | | | | | | < | | | > | | | | | | | | | | | | | | | | < > | | | | | | | | | | | > | 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 | # TIP 292: Allow Unquoted Strings in Expressions State: Draft Type: Project Tcl-Version: 8.7 Vote: Pending Post-History: Author: Brian Griffin <[email protected]> Created: 01-Nov-2006 Keywords: Tcl, expr ----- # Abstract This TIP proposes allowing unquoted words to be recognized as strings in expressions \(**expr**, **if**, **while**\). # Rationale Currently the following fails with a syntax error: set foo bar expr {$foo eq bar} This seems antithetical to the EIAS Tao of Tcl. The **set** command does not require the quotes, so why should **expr**, especially since the operands of the **eq** and **ne** operators are treated as strings. It also seems reasonable for the **==** and **!=** operators to reject unquoted strings as not a valid operand. This provides some enforcement for numerical vs. string comparison by forcing the use of quotes to convert the numeric **==** to a string equality test. The rationale for making such a change is it will make complex code a bit easier to read. For example, I can: set var ENUM_VALUE_ONE switch $var { ENUM_VALUE_ZERO { ... } ENUM_VALUE_ONE { ... } default { ... } } if {[lsearch $supplied_values ENUM_VALUE_ONE] >= 0} { ... } if {[string equals $var ENUM_VALUE_ONE]} { ... } but I must: if {$var eq "ENUM_VALUE_ONE"} { ... } which could lead someone reading the code to incorrectly conclude that ENUM\_VALUE\_ONE is not the same thing as "ENUM\_VALUE\_ONE" or miss the fact that they are the same, especially when using a syntax highlighting editor. # Proposed Change Change the expression parser to accept unquoted words that are not function names as strings. Modify _EqualityExpr_ to reject unqoted strings for "**==**", but allow them for "**eq**". # Draft Implementation None, at the moment. # Copyright This document has been placed in the public domain. |
Name change from tip/293.tip to tip/293.md.
|
| < | | | | | | < | | | > | | | | | | | | | | | | | | | | | | > | 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 | # TIP 293: Argument Expansion with Leading {*} State: Final Type: Project Tcl-Version: 8.5 Vote: Done Post-History: Author: Miguel Sofer <[email protected]> Created: 02-Nov-2006 Obsoletes: 157 ----- # Abstract Tcl shall use **\{\*\}** to denote argument expansion, replacing the current **\{expand\}**. # Rationale There seems to be a consensus that the functionality of **\{expand\}** is exactly what was needed, but the syntax could be nicer. The problem, both back in 2003 and today, is that there is no general agreement on which is the best one. However, the issue of ugliness is regularly revived in the mailing lists so it is not going away soon. Moreover, an alpha release in a popular distribution allows the use of **\{\}** instead of **\{expand\}**. A compromise solution, **\{\*\}**, is less verbose and "ugly" than **\{expand\}**, and less prone to typographical errors than plain **\{\}**. It is inspired using the mnemonic that the character "\*" is already used to denote "all items" in other contexts. # Detailed Proposal After two years experience with **\{expand\}**, this TIP proposes the following amendment to [[157]](157.md): 1. The officially sanctioned expansion syntax will henceforth be **\{\*\}**, in replacement of the previous **\{expand\}**. 2. The usage of both **\{expand\}** and **\{\}** will be deprecated. 3. This is a syntax-only change. # Compatibility Note that this TIP removes **\{expand\}** and **\{\}** as prefix-syntax, which will break code that users might already have in production based off earlier alpha release of 8.5. # Copyright This document has been placed in the public domain. |
Name change from tip/294.tip to tip/294.md.
|
| < | < | | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 294: The "entier" Function: It's Spelt "entire" Author: Lars Hellström <[email protected]> Author: Richard Suchenwirth <[email protected]> State: Rejected Type: Project Vote: Done Created: 03-Nov-2006 Post-History: Keywords: Tcl,number,cast,rename Tcl-Version: 8.5 ----- # Abstract It is proposed that the **expr** function **entier**\(\) introduced by [[237]](237.md) is renamed to **entire**\(\). # Rationale This appears to be a typo. Even though American English differs from British English in that many words which in the latter end in "-re" are spelt "-er", this is not one of these. Neither _Merriam-Webster Online_ nor _dictionary.com_ recognises "entier", whereas both list "entire". A Google search for "entier" reports 61400000 pages, but if one narrows it down to pages in English the count drops to 943000, and even then most of these are in fact written in French. Within the first 60 matches, only 3 show "entier" occurring in English text, and in all these cases it is part of a trademark/product name. Googling for "entier function" shows however that it is a concept discussed in English texts. entier\(\) was one of the standard functions in Algol 60. # Alternatives While the term "entire" meaning "whole" is known in mathematics, it is rarely applied to numbers. The typical thing to be entire is instead a function <http://planetmath.org/encyclopedia/Entire.html> , and that is quite unrelated to integers. Better names could be: * **whole** \("whole number" sounds a bit childish, but unlike "entire number", it would probably be recognised as meaning "integer"\) * **integer** \(this is the proper name for the concept in question\) It could also be argued that the function is rather silly, since "coercing to integer" \(which seems to be the same as truncation, i.e., rounding towards zero\) is mathematically a rather useless operation. More useful operations are rounding to the nearest integer \(available as round\), floor \(rounding downwards\), and ceiling \(rounding upwards\), since these admit tight inequalities that do not depend on the sign of the number. Currently the two latter have to be had by combining **round** and **floor**/**ceil**, whereas separate functions **ifloor** and **iceil** would have been more appropriate. Getting them would however require actually implementing something new. # Implementation This TIP can be implemented by applying the following command prefix to the contents of the files of the Tcl source tree: string map {entier entire Entier Entire} \(It may of course be more convenient to use the search and replace functionality of a text editor.\) Grepping indicates that the only C file affected would be _generic/tclBasic.c**, the only Tcl files affected would be _tests/expr.test_ and _tests/info.test_, and the only documentation file affected would be _doc/mathfunc.n_. # Copyright This document has been placed in the public domain. |
Name change from tip/295.tip to tip/295.md.
|
| < | < | | | | | | | | > | | | | | | | | | | | | | | | | < > | < | > | | | > | 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 | # TIP 295: Enhance Arguments to lrange Author: Andreas Leitgeb <[email protected]> State: Draft Type: Project Vote: Pending Created: 06-Nov-2006 Post-History: Keywords: Tcl,lrange Tcl-Version: 8.7 ----- # Abstract This TIP proposes an enhancement to **lrange** and **string range** that lets them take more than one start-end index pair. # Rationale Sometimes you need to extract a non-continuous selection of elements from some list and build a new list from them. This requires the use of multiple calls to **lrange** and a surrounding **concat** to build the final list. However, since the following fails with a syntax error: lrange {a b c d e f} 1 3 5 5 It would seem a reasonable extension for such a usage of **lrange** to return "b c d f". This would also make following pattern of usage feasible: lassign [lrange $someList 0 2 10 12] var0 var1 var2 var10 var11 var12 The indices should _not_ be required to be in ascending order. This is meant such that the ranges may be overlapping at will. E.g.: [lrange $list 0 end 0 end] == [lrepeat 2 {*}$list] This TIP does NOT change the way each range is interpreted. Reversing lists is not in the scope of this TIP. # Proposed Change Change the implementation of **lrange** to accept any odd number of arguments, with semantics \(upon supply of a correct number of arguments\) equivalent to: proc lrange-new {list args} { set result [list] foreach {start end} $args { lappend result {*}[lrange $list $start $end] } return $result } # Draft Implementation Just the above mentioned procedure, at the moment. # Further Thoughts # Copyright This document has been placed in the public domain. |
Name change from tip/296.tip to tip/296.md.
|
| < | < | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 296: Enhanced Syntax for Pair-Wise Indices Author: Andreas Leitgeb <[email protected]> State: Draft Type: Project Vote: Pending Created: 06-Nov-2006 Post-History: Keywords: Tcl,lrange,lreplace Tcl-Version: 8.7 ----- # Abstract This TIP proposes adding another anchor **s** \(for usage exclusively in end-indices\) that refers to the respective start-index. # Rationale Currently, most commands that accept an index also accept the local keyword **end** as well as simple arithmetics involving this keyword. Commands that accept a pair of indices for a range, require an explicit start and \(inclusive\)end index for the requested subrange. In other languages \(C\+\+/stl, java, ...\) it appears to be more common to specify ranges by start and length. Since the length has a higher tendency of being constant, this seems actually the better idea, anyway. For compatibility reasons, we just cannot simply change all the commands to take offset/length pairs rather than start/end. However we could add a new anchor **s** to be used in the end-index, and allow simple arithmetic on it just like on the other index forms. Specifying a subrange of length 1, one would then simply specify **s** as end-index. For a pair, "s\+1" as end index does it. If the start position of a subrange is obtained as result of a command, currently one typically does in tcl: set offs [...] ... [lrange $list $offs [expr {$offs+1}]] ... A previous TIP has added support to do the following instead: set offs [...] ... [lrange $list $offs $offs+1] ... This TIP aims at making this the new idiom: ... [lrange $list [...] s+1] # Proposed Change Currently there is a function TclGetIntForIndex, which deals with the current **end** anchor. It could be accompanied with a second function \(e.g., TclGetIntForIndex2\) that would accept another argument for the previously calculated index \(from the range-start argument\), and use that in case the new anchor **s** occurs in the range-end index. No change at all is proposed for each range's start index. # Draft Implementation None, at the moment. For a sketch see previous section. In bytecode, it could be done such, that if an **s**-prefix is seen for an \(eventually bytecoded range-related command\), then the current stack-top \(the corresponding start-index\) is dup'ed and then incremented or decremented according to any offset \(s\+\#, s-\#\). # Further Thoughts For **lreplace**, **s-1** as an end-index would actually make it an **linsert** operation. This TIP covers all tcl commands that accept a pair of indices to specify a range, including \(but not limited to\) lrange, lreplace, string range, plus any third-party command written such as to use the proposed **TclGetIntForIndex2** function for parsing end-indices. # Copyright This document has been placed in the public domain. |
Name change from tip/297.tip to tip/297.md.
|
| < | < | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | < > | | | < > | | | | | | | | | | | | | | | < > | < | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 297: Integer Type Introspection and Conversion Author: Don Porter <[email protected]> State: Draft Type: Project Vote: Pending Created: 20-Nov-2006 Post-History: Tcl-Version: 8.7 Keywords: Tcl, number, expression ----- # Abstract This TIP proposes changes to complete the set of commands to test and convert among Tcl's integer types. # Background There are four integer types that appear in Tcl's C API. They are _int_, _long_, _Tcl\_WideInt_, and _mp\_int_. The corresponding routines to pull a value of each of those types from a _Tcl\_Obj_ are **Tcl\_GetIntFromObj**, **Tcl\_GetLongFromObj**, **Tcl\_GetWideIntFromObj**, and **Tcl\_GetBignumFromObj**. These integer types form increasing sets. That is, every _Tcl\_Obj_ that can return an _int_ can also return a _long_, _Tcl\_WideInt_, or _mp\_int_. Strictly speaking, the set of _Tcl\_Obj_ values that can successfully return either and _int_, _long_, or _Tcl\_WideInt_ is platform-dependent, because the size of these types is platform dependent. **Tcl\_GetIntFromObj** accepts integer values in any format \(decimal, binary, octal, hexadecimal, etc., see **TCL\_PARSE\_INTEGER\_ONLY** in [[249]](249.md)\) that are within the inclusive platform-dependent range \(**-UINT\_MAX**, **UINT\_MAX**\). **Tcl\_GetLongFromObj** accepts integer values in any format that are within the inclusive platform-dependent range \(**-ULONG\_MAX**, **ULONG\_MAX**\). **Tcl\_GetWideIntFromObj** accepts integer values in any format that are within the inclusive platform-dependent range \(**-ULLONG\_MAX**, **ULLONG\_MAX**\), or the appropriate equivalent for the platform. **Tcl\_GetBignumFromObj** accepts integer values in any format with \(effectively\) no limit on range. The most common example of platform dependence of results seen at the script level is the different results of **[expr int(.)]** on most 32-bit systems, % set tcl_platform(wordSize) 4 % expr int(1<<31) -2147483648 compared with LP64 systems. % set tcl_platform(wordSize) 8 % expr int(1<<31) 2147483648 These differences show up most unfortunately when implementing algorithms designed to operate explicitly on 32-bit buffers, where the only portable way to do the operations in Tcl is with careful application of masking \(_& 0xffffffff_\). For one well-known example, see the _sha1_ package in tcllib. The additional operations in Tcl expressions harm performance. There are other Tcl routines that pull values from _Tcl\_Obj_ that accept supersets of one of the integer types. An example is **Tcl\_GetIndexFromObj** which will accept anything that **Tcl\_GetIntFromObj** accepts, as well as other string values. There are also Tcl built-in commands that accept arguments that are supersets of one of the integer types. An example is **uplevel** which accepts as its level argument anything that **Tcl\_GetIntFromObj** accepts, as well as other string values. All Tcl commands are ultimately defined by the C command procedures that run to implement them, and when those command procedures use the routines mentioned above to pull values from command arguments, the result is that the Tcl commands will succeed or fail depending on whether or not an integer value of the right type has been provided by the caller. As a simple example: % lindex {} 0xffffffff % lindex {} 0x100000000 bad index "0x100000000": must be integer or end?-integer? In order to avoid errors from commands, a cautious programmer may wish to test whether a value is of an acceptable type before passing it to a command. The **string is integer** command has long offered this facility for commands that require \(a superset of\) an _int_. % string is integer 0xffffffff 1 % string is integer 0x100000000 0 Most of Tcl's built-in commands that accept an integer valued argument require that argument to be acceptable to **Tcl\_GetIntFromObj** and the existing **string is integer** command provides sufficient introspection. [[188]](188.md) created the new command **string is wideinteger**, and that is suitable for testing values for the small number of Tcl commands that strictly require a value acceptable to **Tcl\_GetWideIntFromObj**. Those commands are: after $wide binary format w $wide chan seek $chan $wide chan truncate $chan $wide clock add $wide clock format $wide There are some built-in Tcl commands that require an argument that is acceptable to **Tcl\_GetBignumFromObj**. That is, the argument must be an integer, but no range limit is imposed. Currently there is no test command appropriate for argument checking for these commands. dict incr $dictVar $bignumkey $bignum expr srand($bignum) expr ~$bignum expr $bignum % $bignum expr $bignum << $int expr $bignum >> $bignum expr $bignum & $bignum expr $bignum ^ $bignum expr $bignum | $bignum incr $bignumVar $bignum format $integerSpecifier $bignum There are some built-in Tcl commands that require an argument that is acceptable to **Tcl\_GetLongFromObj**. Currently there is no test command appropriate for argument checking for these commands. binary format i $long binary format s $long binary format c $long file atime $path $long file attributes $path -permissions $long file mtime $path $long Note that the accepted ranges of the **Tcl\_GetFooFromObj** routines can lead to surprising results. For example, **Tcl\_GetIntFromObj** accepts values from **-UINT\_MAX** to **UINT\_MAX**. For some things this is good, since it supports binary format i 0x80000000 on 32-bit platforms, which is a common coding style. However the same range acceptance leads to surprising \(and arguably incorrect, in the presence of bignum support\) things like: % string repeat a -4294967290 aaaaaa It seems there are good uses for both strict and liberal routines for pulling integer ranges from a _Tcl\_Obj_. Compatibility concerns would favor keeping the existing routines liberal, and adding strict counterparts. If this is pursued, however, another collection of **string is** test commands would be needed as well. # Proposed Changes Still pondering how best to react to this background. Discussion invited on TCLCORE. # Compatibility # Reference Implementation # Copyright This document has been placed in the public domain. |
Name change from tip/298.tip to tip/298.md.
|
| < | < | | | | | | | | > | | | | | | | | | < > | | | | | | | | | | | > | 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 | # TIP 298: Revise Shared Value Rules for Tcl_GetBignumAndClearObj Author: Don Porter <[email protected]> State: Final Type: Project Vote: Done Created: 22-Nov-2006 Post-History: Keywords: Tcl,Tcl_Obj Tcl-Version: 8.5 ----- # Abstract This TIP proposes a revision to **Tcl\_GetBignumAndClearObj** to make it easier to use. # Background **Tcl\_GetBignumAndClearObj** was added by [[237]](237.md). Because _mp\_int_ values can be big, the interface is offered to avoid making a copy when the value already in the internal representation of an unshared _Tcl\_Obj_ will no longer be needed and can be moved instead of copied. The basic intent was fine, but in practice, callers must go through these gymnastics to use it: if (Tcl_IsShared(objPtr)) { Tcl_GetBignumFromObj(interp, objPtr, &bigValue); } else { Tcl_GetBignumAndClearObj(interp, objPtr, &bigValue); } It would make for a much more pleasant interface to move the test for a shared value into the routine itself. # Proposed Change When passed a shared _objPtr_, **Tcl\_GetBignumAndClearObj** will no longer panic, but will fall back to the copying behavior of **Tcl\_GetBignumFromObj**. The use of the **Tcl\_GetBignumAndClearObj** interface by a caller no longer means an assertion that _objPtr_ is unshared, and no longer guarantees that _objPtr_ will in fact be cleared, but merely indicates the caller will not be using the value anymore, and does not mind if it is cleared. That's all the caller should care about anyway. Because of these changes in the implications and guarantees, the function is also renamed to **Tcl\_TakeBignumFromObj**. With these changes, the code above may be simplified to: Tcl_TakeBignumFromObj(interp, objPtr, &bigValue); # Compatibility This is a incompatible change only with 8.5 alpha releases. # Reference Implementation Available from <http://sourceforge.net/tracker/index.php?func=detail&aid=1601243&group_id=10894&atid=360894> . # Copyright This document has been placed in the public domain. |
Name change from tip/299.tip to tip/299.md.
|
| < | < | | | | | | | | > | | | | | | | | | | | | > | 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 | # TIP 299: Add isqrt() Math Function Author: Kevin B. Kenny <[email protected]> State: Final Type: Project Vote: Done Created: 24-Nov-2006 Post-History: Tcl-Version: 8.5 Keywords: Tcl, expression, integer, square root ----- # Abstract This TIP proposes a new **expr** math function **isqrt\(\)**. # Background With the advent of large integers, Tcl supports taking the square roots of arguments that lie outside the native floating-point range of the machine. The square roots are returned as floating point numbers if possible. This behaviour is correct when floating-point calculations are intended. There are times, however, when an arbitrary-precision square root is wanted. This root cannot be obtained by evaluating _entier\(sqrt\($n\)\)_, because _sqrt\($n\)_ has already lost precision. # Proposed Change This TIP proposes adding a new math function, _isqrt\($n\)_, that will return the integer part of the square root of _$n_ to arbitrary precision. The argument _$n_ must be numeric and non-negative; it may be either integer or floating-point. # Reference Implementation Tcl Feature Request \#1602534 contains a complete reference implementation for the _isqrt_ function. # Copyright This document has been placed in the public domain. |
Name change from tip/3.tip to tip/3.md.
|
| < | < | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 | # TIP 3: TIP Format Author: Andreas Kupries <[email protected]> Author: Donal K. Fellows <[email protected]> State: Accepted Type: Process Vote: Done Created: 14-Sep-2000 Post-History: ----- # Abstract This TIP is a companion document to the TIP Guidelines [[2]](2.md) and describes the structure and formatting to use when writing a TIP. # Rationale The major goals of this document are to define a format that is * easy to write, * easy to read, * easy to search, and * acceptable to the community at large. The latter is important because non-acceptance essentially means that the TIP process will be stillborn. This not only means basically plain text without much markup but also that we should reuse formats with which people are already acquainted. As the concept of TIPs borrows heavily from Python's PEPs <http://python.sourceforge.net/peps/> their definition on how to structure and format a PEP was reviewed for its suitability of use by the TCT and the community at large. The major points of the format are: * Plain ASCII text without special markup for references or highlighting of important parts. * Mail-like header section containing the meta-information. * Uses indentation to distinguish section headers from section text. A header section like is used in mail or news is something people are acquainted with and fulfils the other criteria too. In addition it is extendable. Using indentation to convey semantic and syntactic information on the other hand is something Pythonistas are used to but here in the Tcl world we are not to the same extent. Looking at bit closer to home we find the Tcl'ers Wiki <http://wiki.tcl.tk/> It does use a plain text format with some very light formatting conventions to allow things like links, images, enumerated and itemized lists. Given the rather high acceptance of this site by the community using its format should be beneficiary to the acceptance of TIPs too. It is therefore proposed to use a combination of a header in mail/news style together with a body employing a slightly extended/modified Wiki format \(mostly backward compatible\) as the format for TIPs. This proposed format is specified in detail below. _Note_ that the use of TAB characters within a TIP is discouraged \(but permitted\) as some mailers \(notably Outlook Express\) make a mess of them. Please be considerate and avoid their use... # Rejected Alternatives But before we specify the format a \(short\) discussion of possible alternatives and why they where rejected. There were three primary competitors to the format specified below, these are SGML/XML, HTML and a markup based upon plain text with embedded tcl-commands, for example like ... [section Abstract] ... * The main disadvantage of SGML and XML based solutions is that they require a much more heavyweight infrastructure for editing and processing documents using them, like specialized editors and extensions for parsing. The format below on the other hand can be processed using pure tcl without extensions. with respect to the specialized editors it should be said that an editor operating on plain ASCII is possible too, but then the text will be difficult to read for humans because of the many occurrences of < and >, conflicting with the requirement to have an 'easy to read' format. > While there are commercial products which can gloss over this, making the editing of XML fairly easy, not everyone currently has access to one or the desire to spend what might be quite a lot of money to acquire one. It is far better to let everyone continue to use their current favourite plain-text editor. * The main problem of HTML is that it is focused on visual and not logical markup. This will make it, although not impossible, but very difficult to parse documents for automatic handling. It is also a poor format for producing printed versions of the documentation from. Experience has also shown that different people have widely different ideas about how the content of TIP documents should be rendered into HTML, an indication that using the language would prove problematic! We can still use HTML as a generated format, but we should not write the documents themselves in it. * The approach of embedding tcl commands into the text of a TIP is \(at least\) as powerful as XML when it comes to automatic processing of documents but much more lightweight. Because of this it is seen as the best of the three rejected alternatives. It was rejected in the end because it was still seen as too heavyweight/demanding for the casual user with respect to learning, easy writing and reading. # Header Format The general format of the header for a TIP is specified in RFC 822 <http://www.rfc-editor.org/rfc/rfc822.txt> . This leaves us to define and explain the keywords, their meaning and their values. The following keywords are _required_, and unless otherwise stated, should occur exactly once: TIP: The number of the TIP as assigned by the TIP editor. Unchangeable later on. Title: Defines the title of the document using plain text. May change during the discussion and review phases. Version: Specifies the version of the document. Usually something like $Revision: 1.8 $. \(Initially $Revision: 1.8 $ should be used, which is then changed by the version control to contain the actual revision number. Author: Contact information \(email address\) for each author. The email address has to contain the real name of the author. If there are multiple authors of the document, this header may occur multiple times \(once per author.\) The format should be approximately like this: _Firstname Lastname <emailaddress>_ State: Defines the state the TIP is currently in. Allowed values are _Draft_, _Active_, _Accepted_, _Deferred_, _Final_, _Rejected_ and _Withdrawn_. This list will be influenced by the finalization of the workflow in [[2]](2.md). Type: The type of the TIP. Allowed values are _Process_, _Project_ and _Informative_. See [[2]](2.md) for more explanations about the various types. Vote: The current state of voting for the TIP. Allowed values are _Pending_, _In progress_, _Done_ and _No voting_. The latter is used to indicate a TIP which doesn't require a vote, for example [[1]](1.md). Created: The date the TIP was created, in the format dd-mmm-yyyy. _mmm_ is the \(English\) short name of the month. The other information is numerical. Example: 14-Sep-2000 > All numeric dates, though more easily internationalised, are not used because the ordering of particularly the month and day is ambiguous and subject to some confusion between different locales. Unix-style timestamps are unreadable to the majority of people \(as well as being over-precise,\) and I \(<[email protected]>\) don't know ISO 8601 well enough to be able to comment on it. Post-History: A list of the dates the document was posted to the mailing list for discussion. Tcl-Version: This indicates the version of Tcl that a Project TIP depends upon \(where it is required.\) Process and Informative TIPs _must not_ have this keyword. The following headers are _optional_ and should \(unless otherwise stated\) occur at most once: Discussions-To: While a TIP is in private discussions \(usually during the initial Draft phase\), this header will indicate the mailing list or URL where the TIP is being discussed. Obsoletes: Indicates a TIP number that this TIP renders obsolete. \(Thanks to Joel Saunier <[email protected]> for suggesting this!\) Obsoleted-By: Indicates a TIP number that renders this TIP obsolete. \(Thanks to Joel Saunier <[email protected]> for suggesting this!\) Keywords: A comma-separated list of keywords relating to this TIP, to facilitate automated indexing and improve search engine results. The following headers are _proposed_ \(by Donald G. Porter <[email protected]>\) but not currently supported: Sponsor: A TCT member that is sponsoring this TIP. May occur multiple times, once per sponsor. Supporter: A person \(not necessarily a TCT member\) who is supporting this TIP. May occur multiple times, once per supporter. Objector: A person \(not necessarily a TCT member\) who is opposed to this TIP. May occur multiple times, once per objector. # Body Format The body of a TIP is split by visually blank lines \(i.e. lines containing nothing other than conventional whitespace\) into units that will be called paragraphs. Each paragraph is in one of the following forms. If the paragraph consists of exactly four minus symbols "----" then it is a separator paragraph and should be rendered as a horizonal rule. If the paragraph consists of a vertical bar "\|" followed by text, then it is a verbatim paragraph. The bar will be stripped from the front of each line and the rest of the text will be formatted literally. Tab characters will be expanded to 8-character boundaries. \(_Note that this is completely incompatible with the Tcl'ers Wiki._\) If the paragraph consists of one or more tildes "~" \(which may be space-separated\) followed by text, then it is a section heading. The text following is the name of the section. In the name of good style, the section heading should have its significant words capitalised. The number of tildes indicates whether this is a section heading, a subsection heading or a subsubsection heading \(one, two or three tildes respectively.\) If the paragraph consists of the sequence "\#index:" followed by some optional text, then it is a request to insert an index. The text following \(after trimming spaces\) indicates the kind of index desired. The default is a "medium" index, and fully compliant implementations should support "short" \(expected to contain less detail\) and "long" \(expected to contain all header details plus the abstract\) as well. Support for other kinds of indices is optional. If the paragraph consists of the sequence "\#image:" followed by some text, then it is a request to insert an image. The first word of the following text is a reference to the image, and the other words are an optional caption for the image \(in plain text.\) Image references that consist of just letters, numbers, hyphens and underscores are handled specially by the current implementation, which can map them to the correct media type for its current output format \(assuming it has a suitable image in its repository.\) All other paragraphs that start with a non-whitespace character are ordinary paragraphs. If a paragraph starts with a whitespace character sequence \(use three spaces and keep the whole paragraph on a single line if you want compatability with the Tcl'ers Wiki,\) a star "\*" and another whitespace character, it is an item in a bulleted list. If a paragraph starts with a whitespace character sequence, a number, a full stop "." and another whitespace character, it is an item in an enumerated list. If the number is 1 then the number of the item is guessed from the current list context, and any other value sets the number explicitly. If you want compatability with the Tcl'ers Wiki, make the initial whitespace sequence be three spaces, the number be 1, and keep the whole paragraph on a single line. If a paragraph starts with a whitespace character sequence, some text \(that includes no tabs or newlines but can include spaces\), a colon and another whitespace character, then it is an item in a descriptive \(a.k.a. definition\) list. The item being described cannot contain advanced formatting \(including any kind of emphasis\) because this is not supported by all formats that a TIP may be viewed in. If a paragraph does not start with a whitespace character sequence, a greater than symbol ">", and then another whitespace character, it is also an ordinary paragraph. \(_Note that this is completely incompatible with the Tcl'ers Wiki._\) Where a paragraph does begin with the sequence described in the preceding paragraph, it is a nested list item \(if the paragraph contained is a list item\) or a subsequent paragraph \(if the paragraph contained is an ordinary paragraph.\) If there's no suitable "enclosing" list context \(i.e. if the preceding paragraph was not part of a list\) the paragraph will be a quotation instead. \(The rules for these continuation paras seem complex at first glance, but seem to work out fairly well in practise, especially since they are only rarely used.\) Within the body text of a \(non-verbatim\) paragraph, there are two styles of emphasis: * italicised emphasis is indicated by enclosing the text within inside double apostrophes "_" * emboldened emphasis is indicated by enclosing the text within inside triple apostrophes "**". The two emphasis styles should not be nested. Special URLs of the form tip:tipnumber are expanded into full URLs to the given TIP through the current formatting engine \(where applicable.\) References of the form [tipnumber] are also expanded as links to the given TIP, but are not displayed as URLs \(the expansion is format dependent, of course.\) Doubled up square brackets are converted into matching single square brackets. Email addresses \(of the form <email@address>\) and ordinary URLs in single square brackets might also be treated specially. The first paragraph of the body of any TIP must be an abstract section title \("~Abstract" or "~ Abstract"\), and the second must be an ordinary paragraph \(and should normally be just plain text, to make processing by tools easier.\) You can compare these rules with those for the Tcl'ers Wiki which are described at <http://wiki.tcl.tk/14.html,> with the following modifications: 1. The text for an item in an itemized, enumerated or tagged list can be split over multiple physical lines. The text of the item will reach until the next empty line. 1. All paragraphs _must_ be split with whitespace. This is a corollary of the above item. 1. A paragraph starting with the character ~ is interpreted as a section heading. Consequently it should be very short so that it renders onto a single line under most circumstances. 1. A full verbatim mode is added. Any line starting with the bar character is reproduced essentially verbatim \(the bar character is removed\). This allows embedding of code or other texts containing formatting usually recognized as special by the formatter without triggering this special processing. This applies especially to brackets and the hyperlinking they provide and their role in tcl code. This is used in preference to the whitespace rule of the Tcl'ers Wiki which is potentially far more sensitive. Our rule makes it extremely obvious what lines are verbatim, and what those lines will be rendered as. 1. Only one style of emphasis within paragraphs is supported. Having multiple emphasis styles \(italic and bold\) not only fails to carry across well in all media, but also makes for confusion on the part of authors and is more difficult to write renderers for too. 1. Images are only supported in a limited way, since under HTML the support for images varies a lot more than most people would like to think, and the concept of an inline image can vary quite a lot between different rendered formats too. # Reference Implementation A reference renderer was created by Donal Fellows <[email protected]> and is installed \(as a behind-the-scenes rendering engine\) on a set of TIP documents <http://www.cs.man.ac.uk/fellowsd-bin/TIP> with the source code to the rendering engine being available <http://sf.net/projects/tiprender/> Note that this code does support nested lists and multi-paragraph items, but this is experimental right now. Examples are presented behind the code itself. ---- # Examples This document itself is an example of the new format. _Examples for nested lists, multi-paragraph items in list's, and quotations._ Here is the source \(itself a demonstration of verbatim text\) * This is a paragraph > * This is an inner paragraph that goes onto two lines. > > * This one's even further in! > > * So's this one. > * Out again > > And a second paragraph here... > * Yet another item. * Outermost level once more. 1. Enumerate? > 1. Deeper? 2. Out again? list item: body text that is relatively long so that we can tell that it laps round properly as a paragraph even though this takes a ridiculous amount of text on my browser... | VERB IN LIST? > nested: body Top-level paragraph once more. > A quotation from someone famous might be rendered something like this. As you can see, it is inset somewhat from the surrounding text. - ''Donal K. Fellows <[email protected]>'' And back to the top-level yet again. Now we show off both ''italic'' and '''bold''' text. ---- and the rendered result * This is a paragraph > \* This is an inner paragraph that goes onto two lines. > > \* This one's even further in! > > \* So's this one. > \* Out again > > And a second paragraph here... > \* Yet another item. * Outermost level once more. 1. Enumerate? > 1. Deeper? 2. Out again? list item: body text that is relatively long so that we can tell that it laps round properly as a paragraph even though this takes a ridiculous amount of text on my browser... VERB IN LIST? > nested: body Top-level paragraph once more. > A quotation from someone famous might be rendered something like this. As you can see, it is inset somewhat from the surrounding text. - _Donal K. Fellows <[email protected]>_ And back to the top-level yet again. Now we show off both _italic_ and **bold** text. ---- _Examples of index generation and image paragraphs._ Here is the code #index: #index:short #index: long #image:3example This is a test caption This is an example long TIP reference tip:3 that should be expanded in a renderer-specific way... This is an example non-reference - ''index[[3]]'' - that should not be rendered as a link (to this document or anywhere else) at all. Note that the dashes in the previous sentence (with whitespace on each side) are candidates for rendering as long dashes (em-dashes) on output-media which support this. Supported URLs: should be http, https, mailto, news, newsrc, ftp and gopher. Test here... > HTTP URL - http://purl.org/thecliff/tcl/wiki/ > HTTP URL in brackets - [http://wiki.tcl.tk] > HTTPS URL - https://sourceforge.net/ > FTP URL - ftp://src.doc.ic.ac.uk/packages/tcl/tcl/ > NEWS URL - news:comp.lang.tcl > MAILTO URL - mailto:[email protected]?subject=TIP3 > Others (might not be valid links!) - gopher://info.mcc.ac.uk, newsrc:2845823825 and here is the rendered result. \#index: \#index:short \#index: long ![This is a test caption](../assets/3example.gif) This is an example long TIP reference tip:3 that should be expanded in a renderer-specific way... This is an example non-reference - _index[[3]](3.md)_ - that should not be rendered as a link \(to this document or anywhere else\) at all. Note that the dashes in the previous sentence \(with whitespace on each side\) are candidates for rendering as long dashes \(em-dashes\) on output-media which support this. Supported URLs: should be http, https, mailto, news, newsrc, ftp and gopher. Test here... > HTTP URL - <http://purl.org/thecliff/tcl/wiki/> > HTTP URL in brackets - <http://wiki.tcl.tk> > HTTPS URL - <https://sourceforge.net/> > FTP URL - ftp://src.doc.ic.ac.uk/packages/tcl/tcl/ > NEWS URL - news:comp.lang.tcl > MAILTO URL - mailto:[email protected]?subject=TIP3 > Others \(might not be valid links!\) - gopher://info.mcc.ac.uk, newsrc:2845823825 ---- _Examples of sections and subsections_ ~Section Heading Section text ~~Subsection Heading Subsection text ~~~Subsubsection Heading Subsubsection text which renders as... # Section Heading Section text ## Subsection Heading Subsection text ### Subsubsection Heading Subsubsection text ---- # Copyright This document has been placed in the public domain. |
Name change from tip/30.tip to tip/30.md.
|
| < | < | | | | | | | | | | | | | | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 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 | # TIP 30: Tk Toolkit Maintainer Assignments Author: Don Porter <[email protected]> Author: Donal K. Fellows <[email protected]> Author: Jan Nijtmans <[email protected]> Author: Todd M. Helfter <[email protected]> Author: Chengye Mao <[email protected]> Author: George B. Smith <[email protected]> Author: Miguel Bañón <[email protected]> Author: Daniel Steffen <[email protected]> Author: Peter Spjuth <[email protected]> Author: Jeff Hobbs <[email protected]> Author: Vince Darley <[email protected]> Author: Donal K. Fellows <[email protected]> Author: Benjamin Riefenstahl <[email protected]> Author: Pat Thoyts <[email protected]> Author: Vince Darley <[email protected]> Author: Peter Spjuth <[email protected]> State: Draft Type: Informative Vote: Pending Created: 09-Mar-2001 Post-History: ----- # Abstract This document keeps a record of who maintains each functional area of Tk \([[23]](23.md)\). # Assignments Listed below are Tk's functional units, in the same order as in [[23]](23.md). See [[23]](23.md) for the precise definition of what code belongs to what area, and how maintainers designate their support for platform-specific portions of the code. The area names listed below are also the Categories in the SourceForge Tracker for the Tk Toolkit <http://sourceforge.net/tracker/?group_id=12997> . For each of Tk's functional units, the following maintainers are assigned: 1. _Bindings_ - Jeff Hobbs <[email protected]> 2. _Appearance_ - Jeff Hobbs <[email protected]>, Daniel Steffen <[email protected]> \(Mac OS X\), Jim Ingham <[email protected]> \(Mac OS X\) 3. _[*button] and [label]_ - Allen Flick <[email protected]>, Jeff Hobbs <[email protected]>, Daniel Steffen <[email protected]> \(Mac OS X\), Jim Ingham <[email protected]> \(Mac OS X\), Vincent Darley <[email protected]> \(Mac OS X\) 4. _Canvas Basics_ - Jeff Hobbs <[email protected]>, Jan Nijtmans <[email protected]> 5. _Canvas Items_ - Jeff Hobbs <[email protected]>, Jan Nijtmans <[email protected]> 6. _Canvas PostScript_ - Jeff Hobbs <[email protected]> 7. _[entry]_ - Allen Flick <[email protected]>, Jeff Hobbs <[email protected]> 8. _[frame] and [toplevel]_ - Jeff Hobbs <[email protected]>, Peter Spjuth <[email protected]> 9. _[listbox]_ - Allen Flick <[email protected]>, Jeff Hobbs <[email protected]> 10. _Generic Menus_ - Jeff Hobbs <[email protected]>, Todd Helfter <[email protected]> 11. _AquaMac OS X Menus_ - George B. Smith <[email protected]>, Daniel Steffen <[email protected]>, Jim Ingham <[email protected]>, Vincent Darley <[email protected]> 12. _Unix Menus_ - Jeff Hobbs <[email protected]>, Todd Helfter <[email protected]> 13. _Win Menus_ - Jeff Hobbs <[email protected]>, Todd Helfter <[email protected]> 14. _[message]_ - Jeff Hobbs <[email protected]> 15. _[scale]_ - Jeff Hobbs <[email protected]>, Daniel Steffen <[email protected]> \(Mac OS X\), Jim Ingham <[email protected]> \(Mac OS X\) 16. _[scrollbar]_ - Jeff Hobbs <[email protected]>, Daniel Steffen <[email protected]> \(Mac OS X\), Jim Ingham <[email protected]> \(Mac OS X\) 17. _[spinbox]_ - Jeff Hobbs <[email protected]> 18. _[text]_ - Jeff Hobbs <[email protected]>, Vince Darley <[email protected]> 19. _Menubars \(obsolete\)_ - Jeff Hobbs <[email protected]> 20. _[tk_optionMenu]_ - Jeff Hobbs <[email protected]> 21. _[panedwindow]_ - Jeff Hobbs <[email protected]> 22. _Style Engine_ - Frédéric Bonnet <[email protected]> 23. _Option Parsing_ - Jeff Hobbs <[email protected]>, Daniel Steffen <[email protected]> \(Mac OS X\), Jim Ingham <[email protected]> \(Mac OS X\) 24. _Relief_ - Jeff Hobbs <[email protected]>, Frédéric Bonnet <[email protected]> 25. _Built-in Bitmaps_ - Jeff Hobbs <[email protected]>, Jan Nijtmans <[email protected]>, Daniel Steffen <[email protected]> \(Mac OS X\), Jim Ingham <[email protected]> \(Mac OS X\) 26. _Conversions From String_ - Jeff Hobbs <[email protected]> 27. _Objects_ - Jeff Hobbs <[email protected]> 28. _Utility Functions_ - Jeff Hobbs <[email protected]> 29. _Colormaps and Visuals_ - Jeff Hobbs <[email protected]> 30. _Color Names_ - Jeff Hobbs <[email protected]>, Daniel Steffen <[email protected]> \(Mac OS X\), Jim Ingham <[email protected]> \(Mac OS X\) 31. _Cursor Names_ - Jeff Hobbs <[email protected]>, Daniel Steffen <[email protected]> \(Mac OS X\), Jim Ingham <[email protected]> \(Mac OS X\) 32. _Key Symbols_ - Jeff Hobbs <[email protected]>, Daniel Steffen <[email protected]> \(Mac OS X\), Jim Ingham <[email protected]> \(Mac OS X\), Benjamin Riefenstahl <[email protected]> \(Mac OS X\) 33. _Generic Dialog Support_ - Donal K. Fellows <[email protected]>, Jeff Hobbs <[email protected]> 34. _[tk_chooseColor]_ - Donal K. Fellows <[email protected]> \(Unix\), Jeff Hobbs <[email protected]> 35. _[tk_dialog]_ - Donal K. Fellows <[email protected]> \(Unix\), Jeff Hobbs <[email protected]>, Daniel Steffen <[email protected]> \(Mac OS X\), Jim Ingham <[email protected]> \(Mac OS X\) 36. _[tk_chooseDirectory]_ - Donal K. Fellows <[email protected]> \(Unix\), Jeff Hobbs <[email protected]> 37. _[tk_get*File]_ - Donal K. Fellows <[email protected]> \(Unix\), Jeff Hobbs <[email protected]> 38. _[tk_messageBox]_ - Donal K. Fellows <[email protected]> \(Unix\), Jeff Hobbs <[email protected]> 39. _Image Basics_ - Jan Nijtmans <[email protected]>, Donal K. Fellows <[email protected]> 40. _Bitmap Images_ - Jan Nijtmans <[email protected]>, Kevin Griffin <[email protected]> 41. _Photo Images_ - Jan Nijtmans <[email protected]>, Donal K. Fellows <[email protected]> 42. _Photo Image\|GIF_ - Jan Nijtmans <[email protected]> 43. _Photo Image\|PPM_ - Jan Nijtmans <[email protected]>, Donal K. Fellows <[email protected]> 44. _Generic Fonts_ - Jeff Hobbs <[email protected]> 45. _Aqua Fonts_ - George B. Smith <[email protected]>, Daniel Steffen <[email protected]>, Jim Ingham <[email protected]>, Benjamin Riefenstahl <[email protected]> 46. _Unix Fonts_ - Jeff Hobbs <[email protected]> 47. _Win Fonts_ - Jeff Hobbs <[email protected]>, Pat Thoyts <[email protected]> 48. _Geometry Management_ - Jeff Hobbs <[email protected]>, Chengye Mao <[email protected]> 49. _[grid]_ - Jeff Hobbs <[email protected]>, Peter Spjuth <[email protected]> 50. _[pack]_ - Jeff Hobbs <[email protected]>, Peter Spjuth <[email protected]> 51. _[place]_ - Jeff Hobbs <[email protected]>, Peter Spjuth <[email protected]> 52. _[clipboard]_ - Jeff Hobbs <[email protected]> Joe English <[email protected]> \(Unix\), Daniel Steffen <[email protected]> \(Mac OS X\), Jim Ingham <[email protected]> \(Mac OS X\) 53. _[selection]_ - Jeff Hobbs <[email protected]>, Joe English <[email protected]> \(Unix\) 54. _[console]_ - Jeff Hobbs <[email protected]>, Chengye Mao <[email protected]> 55. _[focus]_ - Jeff Hobbs <[email protected]> 56. _[grab]_ - Jeff Hobbs <[email protected]> 57. _[option]_ - Allen Flick <[email protected]>, Jeff Hobbs <[email protected]> 58. _[send]_ - Allen Flick <[email protected]>, Jeff Hobbs <[email protected]>, Daniel Steffen <[email protected]> \(Mac OS X\), Jim Ingham <[email protected]> \(Mac OS X\), Pat Thoyts <[email protected]> 59. _[tk_focus*]_ - Jeff Hobbs <[email protected]> 60. _[tk_setPalette]_ - Jeff Hobbs <[email protected]> 61. _Safe Tk_ - Jeff Hobbs <[email protected]> 62. _Geometry Functions_ - Jeff Hobbs <[email protected]>, Chengye Mao <[email protected]> 63. _Tk\_Win Functions_ - Jeff Hobbs <[email protected]> 64. _Graphic Contexts_ - Jeff Hobbs <[email protected]> 65. _Generic Window Operations_ - Jeff Hobbs <[email protected]> 66. _Aqua Window Operations_ - George B. Smith <[email protected]>, Daniel Steffen <[email protected]>, Jim Ingham <[email protected]>, Vincent Darley <[email protected]> 67. _Unix Window Operations_ - Jeff Hobbs <[email protected]>, Joe English <[email protected]> 68. _Win Window Operations_ - Jeff Hobbs <[email protected]>, Chengye Mao <[email protected]> Vincent Darley \(maintainer for wm iconbitmap only\) <[email protected]> 69. _Events_ - Jeff Hobbs <[email protected]> 70. _Event Loop_ - Jeff Hobbs <[email protected]>, Jan Nijtmans <[email protected]> 71. _Error Handling_ - Jeff Hobbs <[email protected]> 72. _Atoms_ - Jeff Hobbs <[email protected]> 73. _Argv Parsing_ - Jeff Hobbs <[email protected]> 74. _Application Embedding_ - Daniel Steffen <[email protected]> \(Mac OS X\), Jim Ingham <[email protected]> \(Mac OS X\), Don Porter <[email protected]> 75. _wish_ - Daniel Steffen <[email protected]> \(Mac OS X\), Jim Ingham <[email protected]> \(Mac OS X\), 76. _Widget Tour_ - Donal K. Fellows <[email protected]>, Jeff Hobbs <[email protected]> 77. _Square Demo_ - Jeff Hobbs <[email protected]> 78. _Other Demos_ - Donal K. Fellows <[email protected]>, Jeff Hobbs <[email protected]> 79. _L10N_ - Jan Nijtmans <[email protected]>, Miguel Bañón <[email protected]> 80. _Release Notes_ - Jeff Hobbs <[email protected]> 81. _Portability_ - Jeff Hobbs <[email protected]> 82. _X11 Emulation_ - Jeff Hobbs <[email protected]> 83. _Mac OS X Build_ - George B. Smith <[email protected]>, Daniel Steffen <[email protected]>, Jim Ingham <[email protected]>, 84. _Unix Build_ - Jeff Hobbs <[email protected]>, Mo DeJong <[email protected]>, Lloyd Lim <[email protected]> 85. _Win Build_ - Jeff Hobbs <[email protected]>, Mo DeJong <[email protected]>, Pat Thoyts <[email protected]> 86. _Test Tools_ - Allen Flick <[email protected]>, Jeff Hobbs <[email protected]>, Daniel Steffen <[email protected]> \(Mac OS X\), Jim Ingham <[email protected]> \(Mac OS X\) 87. _Logos_ - Jeff Hobbs <[email protected]> Daniel Steffen <[email protected]> \(Mac OS X\), Jim Ingham <[email protected]> \(Mac OS X\), # General Categories The following categories in Tk's SourceForge Tracker do not refer to any specific portion of Tk. Reports in these categories should be mapped to categories corresponding to a maintained area of Tk, when seeking the appropriate maintainer: 1. _Other_ - Reports that span multiple categories. # Areas Without Maintainers Those functional areas without a maintainer are maintained by the Tcl Core Team with each change requiring TYANNOTT review. # Copyright This document has been placed in the public domain. |
Name change from tip/300.tip to tip/300.md.
|
| < | < | | | | | | | | > | | | | | | | | | | | | | | | > | 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 | # TIP 300: Examine Glyph Substitution in the 'font actual' Command Author: Kevin B. Kenny <[email protected]> State: Final Type: Project Vote: Done Created: 25-Nov-2006 Post-History: Tcl-Version: 8.5 Keywords: Tk ----- # Abstract This TIP proposes enhancing the **font actual** command to allow determining the actual font to be used when rendering a specific character. # Background Tk, when rendering strings in a widget, often needs to augment the characters in the requested font with characters borrowed from other fonts. As of the date of this TIP, there is no way for a program to introspect this mechanism. This ability has been requested by several user interface designers, because the interfaces are often more attractive if the substitute fonts are used directly, or simply to determine what font was chosen. # Proposed Change This TIP proposes modifying the **font actual** command to have the syntax: > **font actual** _font_ ?**-displayof** _window_? ?_option_? ?**--**? ?_char_? The _font_, **-displayof** and _option_ arguments are unchanged from the current [font actual] command. The **--** option marks the end of options. It is needed if _option_ is not supplied and _char_ may be a hyphen, to distinguish _char' from a misspelt option. The _char_ option must be a single character. The result of the command, if the _char_ option is supplied, is the actual font used to render the given character, rather than the base font. # Reference Implementation A reference implementation for the proposed feature, including documentation and test suite updates, is at SourceForge as Tk Patch \#1602955. # Copyright This document has been placed in the public domain. |
Name change from tip/301.tip to tip/301.md.
|
| < | < | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 301: Split Bidirectional Channels For Half-Close Author: Alexandre Ferrieux <[email protected]> State: Withdrawn Type: Project Vote: Pending Created: 11-Dec-2006 Post-History: Tcl-Version: 8.6 Obsoleted-By: 332 ----- # Abstract This TIP proposes to introduce a **chan split** command allowing to access both sides of a bidirectional channel \(r\+ pipe, or socket\) as separate Tcl channels, in order to be able to close them separately. This would give Tcl the same level of control that the OS enjoys on the lifetime of such bidirectional connections. # Background Bidirectional channels allow Tcl to make an efficient use of a "filter process", by exchanging data back and forth over an abstract "single" channel. However, this single channel abstraction comes with a too coarse-grained **close** primitive. Indeed, it closes both directions simultaneously, while it is often desirable to close "gracefully" the half-connection _to_ the filter process, leaving the return path open. The effect of such a half-close is that the filter receives a bona fide EOF alone, without a nearly simultaneous SIGPIPE on its write end if it happens to be writing at that time. Moreover, if the filter is itself comprised of a pipeline of processes, some of which doing buffered I/O, then this graceful EOF may be the only way of flushing the chain and receiving back precious data. This technique is supported by all modern OSes: for pipes there are actually two separate file descriptors/handles, and it suffices to close\(\) the write side; for sockets, a single fd is used, but a specific syscall, shutdown\(\), brings back the ability to half-close. Hence it is fairly natural for a universal "OS glove" like Tcl to expose this universal feature. # Proposed Change This TIP proposes to add a **chan split** subcommand to **chan**, with the syntax: > **chan split** _channel_ The _channel_ argument indicates the bidirectional channel to be split. The command returns a two element list, with the first element being the name of the channel that is open for reading only, and the second element being the name of the channel that is open for writing only. After calling [**chan split** _channel_], _channel_ is still opened, but now shares its internal descriptor\(s\)/handle\(s\) with the returned readable and writable channel. Then, simple "reference counting" at the descriptor level decides when a **close** translates into an actual close\(\)/shutdown\(\) at the OS level: a descriptor is shut down only when all its Tcl-level representatives have been closed. As a consequence, the normal idiom for the graceful shutdown described above, is to close the bidirectional channel immediately after splitting it. Later, the sequence is initiated by closing the write side, then waiting for all data and EOF on the read side: foreach {rch wch} [chan split $ch] break close $ch ... # initiate graceful shutdown close $wch # get back final data set last [read $rch] close $rch In the case of a pipe, the [close $rch] has the same semantics as [close $ch] would have had, that is, waiting for the child's exit status, and raising a Tcl exception if nonzero. # Rationale I had initially only asked for an extension of **close**, and Eric Hassold brought up the superbly elegant idea of **chan split**. Later on, Neil Madden came with the equally beautiful **chan restrict**, which initially won my preference. Only dirty concern for the amount of work needed vs. actual uses, did make me regard the less ambitious **chan split** as a more reasonable target \(sorry for the change, Neil\). Also, it was suggested that the separation between the read and write side could be exploited not only by **close**, but also by **fconfigure**, e.g., to allow for a blocking-read/nonblocking-write, or different baudrates for both directions of a serial port, etc. I feel those are possible later extensions of **chan split**, however their implementation may be much harder than the **close** case, because \(1\) ioctls/fcntl\(\) are not always suited for separation, and \(2\) multiplexing them is not possible with Threads. # Reference Implementation I have not yet written a reference implementation; I assume somebody with a more fluent practice of the channel system implementation will do so more efficiently. However, community feedback on news:comp.lang.tcl seems to witness some interest in the concept. As a last resort, I can give it a try, of course. # Copyright This document has been placed in the public domain. |
Name change from tip/302.tip to tip/302.md.
|
| < | < | | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 302: Fix "after"'s Sensitivity To Adjustments Of System Clock Author: Alexandre Ferrieux <[email protected]> Author: Kevin Kenny <[email protected]> State: Draft Type: Project Vote: Pending Created: 13-Dec-2006 Post-History: Keywords: Tcl,time changes Tcl-Version: 8.7 ----- # Abstract Currently, **after** tasks can be drastically delayed or sped up simply by adjusting the system clock. This is due to the implementation's use of an _absolute_ target date based on the system clock. The idea of this TIP is to use another timebase for this purpose: the count of ticks from boot, which is not affected by system time adjustments. # Background The basis of the implementation of **after** is, on each call to **vwait**, to compute the _timeout_ argument to select\(\) by difference between the stored target date of the earliest event and the current system date \(_gettimeofday\(\)_\). This is perfect while the system date ticks regularly. But if, say, the clock is set back by 5 minutes, then an after handler scheduled 1 second ago which was just about to fire, will have 5 minutes yet to wait before its \(unmodified\) target date is reached. So, if this handler was part of a 1-Hz periodic task, there will be a huge gap of 5:01 between two ticks at that point. If some other component is expecting some kind of regularity, even with a conservative timeout of 10 times the expected period, it _will_ time out, decide the periodic task is dead, and possibly take drastic action. # Proposed Change This TIP proposes to use other timebases instead of gettimeofday\(\) in the vwait/after code: **times\(\)** in unix, **GetTickCount\(\)** in Windows. These clocks suffer _no_ sysadmin tinkering. # Potential Break Of Compatibility It has been objected that _some_ applications today may be using **after** with an _absolute_ spirit; IOW such apps are supposed to _rely_ on the fact that the after handler will fire when the system clock equals the target date computed once for all when **after** was called. A prototype example would be a crontab-like task, which would itself compute the offset by difference between the target date and the current **clock seconds**. ## Arguments For Breaking It Anyway 1. This _absolute_ interpretation is far from being natural, because **after**'s argument is an _offset_. 2. This technique is not usable for a longer range than 25 days \(MAXINT milliseconds\), so not applicable e.g. for a personal schedule. 3. The **overwhelming** majority of uses of **after** takes the _relative_ interpretation \(periodic tasks, timeouts\) and _cannot_ work correctly today. 4. If this TIP were implemented incompatibly \(i.e. without a specific flag to **after**\), those _absolute-minded_ apps could simply be adapted _and_ improved in both robustness and range by using a periodic task which polls **clock seconds**. 5. There is little evidence that the total number of _absolute-minded_ apps exceeds **one** \(see discussion on news:comp.lang.tcl "[after] fooled by shifting date"\) # Syntax For Not Breaking It If Deemed Useful Of course, if this supposed singleton is in fact many, or has enough weight to preclude an improvement of the rest of Tcl timers, we can do: > **after -robust** _millisecs_ or any other colorful option name. But in this case there is a high risk that: _either_ **after -robust** becomes the dominant use, thus cluttering the code in many places, _or_ people remain largely unaware of the problem, stick to the default **after**, and space shuttles fall by dozens. # Escalation To The TCT I'll leave it to the TCT to arbitrate, and decide whether _fixing_ a widely used core primitive can outweigh breaking a rare and clumsy use. # Reference Implementation I have not yet written a reference implementation; I assume somebody with a more fluent practice of the core will do so more efficiently. However, gentle arm twisting, etc. # Copyright This document has been placed in the public domain. # Comments The _times_ function in Unix is _not_ an appropriate time base. It reports the user and system time \(CPU time, in other words\) of the currently executing process and its children. As far as I have been able to determine, Unix assumes that the system time reported by _gettimeofday_ is the sole time base for absolute timing; if multiple timers are required in a single process, _gettimeofday_ appears to be the only reference that is available. |
Name change from tip/303.tip to tip/303.md.
|
| < | < | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | < | > | > | 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 | # TIP 303: Enhance 'llength' Command to Support Nested Lists Author: Wolf-Dieter Busch <[email protected]> State: Draft Type: Project Tcl-Version: 8.7 Vote: Pending Created: 29-Jan-2007 Post-History: Keywords: Tcl, lindex ----- # Abstract The command **llength** currently returns the length of a list. Sometimes it is desirable to know the length of a nested list. This TIP proposes an improvement to **llength** to do that. # Description Currently, finding the length of a nested list requires the combination of **llength** and **lindex**. This works, but is not very clean for a comparatively common operation when you compare with straight **lindex** usage. This TIP proposes to enhance **llength** so that it also does the indexing, making it's usage in such situations cleaner and less subject to programming errors. ## Proposed Change The **llength** command shall be updated to have syntax like this: > **llength** _list_ ?_indexList_ ...? When no _indexList_ is supplied, the current behavior is used. When one or more _indexList_ arguments are supplied, they are used to restrict which part of _list_ is taken the length of, just as if **lindex** had been used to index into _list_. Thus, [**llength {a {b c} d}**] shall return 3 as nowadays, [**llength \{a \{b c\} d\} 1**]> shall return the length of the nested list on index 1, here \{b c\} => 2, and [**llength {a {b c} d} 1 0**] shall return the length of the nested list on index 0 of nested list on index 1, i.e., 1 in this case. ## Compatibility As this only changes a way of use of the **llength** that currently returns an error, there are no compatibility problems. # Example Implementation The procedure **idxllength** \(below\) does what is described above, but inefficiently: proc idxllength args { llength [lindex {*}$args] } # Copyright This document has been placed in the public domain. |
Name change from tip/304.tip to tip/304.md.
|
| < | < | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 304: A Standalone [chan pipe] Primitive for Advanced Child IPC Author: Alexandre Ferrieux <[email protected]> State: Final Type: Project Vote: Done Created: 07-Feb-2007 Post-History: Keywords: Tcl,exec,process,subprocess,pipeline,channel Tcl-Version: 8.6 ----- # Abstract Currently, it is not easy to get both \(separate\) dataflows from the stdout and stderr of a child. BLT's **bgexec** does this in an extension, and could be added to the core. But the point of this TIP is to show that a much smaller code addition can provide a lower-level primitive with much more potential than **bgexec**'s: a _standalone pipe_ creation tool like TclX's **pipe** command. # Background Getting back both stdout and stderr from a child has long been an FAQ on news:comp.lang.tcl, to the point that **bgexec** has been offered in an extension, BLT, whose main job is very remote from IPC. Now this has been a problem for many, who didn't want to have the problems of distributing a script depending on an extension. Moreover, **bgexec** does not scale up, in that it cannot bring back the separate stderrs of all four children in: set ff [open "|a | b | c | d" r] A popular workaround for script-only purists is to spawn an external "pump" like _cat_ in an [**open** ... r+], and redirect the wanted stderr to the write side of the pump. Its output can then be monitored through the read side: set pump [open "|cat" r+] set f1 [open "|cmd args 2>@ $pump" r] fileevent $f1 readable got_stdout fileevent $pump readable got_stderr Now this is all but elegant of course, difficult to deploy on Windows \(where you need an extra cat.exe\), and not especially efficient since the "pump" consumes context switches and memory bandwidth only to emulate a _single_ OS pipe when Tcl is forced to create _two_ of them via [**open** ... r+]. For this latter performance issue, a better alternative is a named pipe. But it is even harder to create on Windows, and it is a nightmare to handle its lifecycle properly \(it doesn't die automagically with the creating process; blocks on open\(\) if other side is not ready\). # Proposed Change All this points to the obvious solution: steal TclX's **pipe** command, which wraps the OS's pipe\(\)/CreatePipe\(\) syscall, yielding two Tcl channels wrapping the read and write side of the underlying pipe. TclX's **pipe** command allows two syntaxes: pipe pr pw foreach {pr pw} [pipe] break Its application to following stderr is straightfoward: pipe pr pw set f1 [open "|cmd args 2>@ $pw" r] fileevent $f1 readable got_stdout fileevent $pr readable got_stderr ## Specification The basic functionality is to return a pair of channels, so the script-level API does just that: > **chan pipe** Create a pipe, and return a list of two channels wrapping either side of the pipe. The first element is the side opened for reading, the second for writing: lassign [chan pipe] pr pw Subsequently, anything written to $pw will be readable on $pr. We purposefully drop the other [pipe pr pw] syntax from TclX, for the sake of minimality. ## C Interface A counterpart to **chan pipe** is added to Tcl's C API: > int **Tcl\_CreatePipe**\(Tcl\_Interp \*_interp_, Tcl\_Channel \*_rchan_, Tcl\_Channel \*_wchan_, int _flags_\) The _interp_ argument is used for reporting errors and registering the channels created, the _rchan_ and _wchan_ arguments point to variables into which to place the channels for each end of the pipeline, and the _flags_ argument is reserved for future expansion. # Discussion It has been in TclX for years, so it is fireproof. The code can be directly copied from there, and is dead simple, just calling Tcl\_MakeFileChannel and Tcl\_RegisterChannel on both fds/handles. Just the low-level syscall changes between unix and windows. ## Additional Benefits It should also be noted that this primitive allows to deprecate the use of [**open** "\|..."] and **pid** themselves ! lassign [chan pipe] p1r p1w lassign [chan pipe] p2r p2w set pids [exec cmd $args >@ $p1w 2>@ $p2w &] fileevent $p1r readable got_stdout fileevent $p2r readable got_stderr Taking this idea one step further, one can even deprecate the "\|" in **exec**, with: exec a | b | c & being rewritten as: exec a >@ $p1w & exec b <@ $p1r >@ $p2w & exec c <@ $p2r & \(I'm not crazy about actually deprecating ol'good and concise idioms in favour of the tedious lines above; however as an orthogonality worshipper I like to think it would be theoretically possible to reimplement them in pure Tcl thanks to the added power of one tiny extra primitive\) A more serious advantage, is that it allows the "half-close" of a command pipeline \(detailed in [[301]](301.md) which the current TIP makes partly obsolete\). Indeed lassign [chan pipe] pr pw lassign [chan pipe] qr qw exec a <@$pr >@$qw & allows to close just the read side with close $pw and still read all the output of the command up to its EOF: while {[gets $qr line]>=0} {...} which is notoriously impossible with set pq [open |a r+] # Directions for Future Work On unix, there's no reason to limit the use of unnamed pipes to stdout and stderr. An arbitrary pipe topology can be set up between several childs with descriptors 3,4,5... For this we could imagine a natural extension of **exec**'s **2>@** to **3>@**, **4<@**, etc. exec foo >@ $p 3>@ $q 4<@ $r & exec bar <@ $q >@ $r 4<@ $p & Of course, such uses are extreme, but useful in complicated IPC setups to achieve much better performance \(through direct point-to-point pipes\) than would a simpler "star" or "blackboard" topology \(where all children write back to a central message routing process\). # Reference Implementation A patch against the Tcl HEAD \(8.6\) is located at <http://sf.net/tracker/?func=detail&aid=1978495&group\_id=10894&atid=310894> # Copyright This document has been placed in the public domain. |
Name change from tip/305.tip to tip/305.md.
|
| < | < | | | | | | | | > | | | | | | | | | | | | > | 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 | # TIP 305: ANSI Escape Sequence Support for Windows's Console Channel Driver Author: David Gravereaux <[email protected]> State: Withdrawn Type: Project Vote: Pending Created: 21-Feb-2007 Post-History: Discussions-To: news:comp.lang.tcl Tcl-Version: 8.5 ----- # Abstract The console channel driver for windows \(win/tclWinConsole.c\) could support colors, cursor movement, and scrolling by embedding such commands in the stream to the console in the age-old tradition of ANSI\_X3.64-1979 escapes. By filtering-out such commands in the DriverOutputProc and doing the command actions, greater cross-platform support is enabled to other platforms \(such as Linux\) that have ANSI support. # Rationale A long time ago, in a land far, far away... DOS programmers wrote character-mode applications for a screen that was 80x25 cells large and had 16 colors and a few special attributes using a strange codepage called _IBM PC_ or _CP437_. And life wasn't that bad. Currently, there appears to only be two ways to write such an application in Tcl: * Use the services of TWAPI to call the native Console API intrinsics. * Use the ck shell \(Curses Tcl Toolkit\). This change proposal is similar to the first option, but the commands are placed in the stream in a standardized manner that gains us immediate support with Linux. This change proposal is different than the second option in that only the output direction of the console driver is modified. No support is proposed for such things as raw keyscan and mouse events. This change proposal will not effect the opening modes of the console, therefore will not have an adverse change to any current scripts. # Specification This TIP proposes two changes visible at the script level. Firstly, the **fconfigure** command will be able to set the speed of channels directed to the Windows console \(often being stdout and stderr\) via a **-baud** option. Secondly, channels directed to the Windows console will interpret ANSI control sequences as ANSI control sequences \(subject to the limitations outlined below\) and not directives to write characters. The _blink_ and _underline_ SGR modes can not be supported due to OS limitations, nor can the color palette be modified to affirm color consistency. _reverse_ and _concealed_ SGR modes can both be emulated, but _concealed_ has a security risk and is not a replacement for turning local echo off. # Reference Implementation A patch is currently being worked on. There is an ANSI test extension for wish available <http://www.pobox.com/~davygrvy/tclstuff/winAnsiCon12_pack.zip> that contains numerous test screens \(some with ansimations\) and appears to work perfectly. # Copyright This document has been placed in the public domain. |
Name change from tip/306.tip to tip/306.md.
|
| < | < | | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | < | > | | | | | | | | | | < | > | | | | | | | | | | | | | | | | | | | | | | < > | | | | | | | | | > | 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 | # TIP 306: Auto-Naming Widgets Author: Koen Danckaert <[email protected]> Author: Richard Suchenwirth <[email protected]> State: Rejected Type: Project Vote: Done Created: 11-Jun-2007 Post-History: Keywords: automatic,Tk,widget,naming Tcl-Version: 8.6 ----- # Abstract A Tk programmer must give every widget a unique name. This is often quite annoying, especially for widgets whose name is stored in a variable \(which also must be given a name\). This TIP proposes a small extension to generate automatic names for widgets. # Rationale Every Tk widget must be given a unique name. This is needed internally for Tk and also for the programmer to be able to refer to it. Quite often, and as recommended in many Tk coding guidelines \(e.g. <http://www.beedub.com/book/2nd/TKINTRO.doc.html\),> the widget names are stored in variables and only referred to indirectly. These variables must also be given a name, which may lead to confusion, and requires more inventivity of the programmer than needed. An example from the BWidget source code: set status [frame $path.status -background $bg] set label [label $status.label] set indframe [frame $status.indf -background $bg] set prgframe [frame $status.prgf -background $bg] Other cases where widget names are unimportant from a programmer's viewpoint, are widgets which are never referred to after creation, and those which are only referred to by other means \(e.g. by a textvariable\). Example: pack [label .name_label -text "Enter name:"] -side left pack [entry .name_entry -textvariable name] -side left In all those cases, it would be helpful if Tk could generate the widget names itself. Further motivation for this can be found in the following: * Tcl/Tk already uses auto-naming for other things, e.g. for channels and for images. * In Python and Ruby's Tk implementation, automatic widget names are the default. For example, a label in TkInter is normally created as: mylabel = Label(parentframe, text="something") > In this case the Tk widget name will be something like _$parentframe_.**123**. If you really want to assign a name yourself, you can use the optional _name_ argument: mylabel = Label(parentframe, text="koen", name = "mylabel") Currently the widget creation commands already return the widget name, which is always the exact name the programmer has supplied. This makes it easy to make an \(almost\) backwards compatible extension, as presented below. # Specification When creating a new widget with a name that ends with "**%**", the "%" will be replaced by a counter. The actual widget name is then returned. Depending on the chosen implementation, there may be one global counter or each parent widget can have its own counter. % button .% .1 % set f [frame .%] .2 % label $f.% .2.3 % set p [frame .prefix%] .prefix4 % label $p.%a%b%c%% .prefix3.%a%b%c%5 The examples above can now be written as: set status [frame $path.% -background $bg] set label [label $status.%] set indframe [frame $status.% -background $bg] set prgframe [frame $status.% -background $bg] pack [label .% -text "Enter name:"] -side left pack [entry .% -textvariable name] -side left # Reference Implementation See SourceForge patch \#1735008<http://sf.net/support/tracker.php?aid=1735008> . The reference implementation keeps a counter in the TkMainInfo structure, which is thread-local. # Compatibility ## Backward Compatibility The presented extension is backward compatible, except for existing code which uses widget names ending on "%". Even this will only be a problem if the widgets are referenced directly \(i.e. not by a variable\) after creation. ## Forward Compatibility This is another issue. Megawidgets which want to support the new naming scheme, will probably have to be adapted. In particular, when they are written as: proc mymegawidget {win args} { # do some stuff with $win # ... # Create the hull frame frame $win -class MyMegaWidget # Create internals label $win.title -text "Title" # ... } they will have to be rewritten in the following way: proc mymegawidget {w args} { # Create the hull frame (returns the actual widget name) set win [frame $w -class MyMegaWidget] # do some stuff with $win # ... # Create internals label $win.title -text "Title" # ... } In Tk itself, there is one such example which has to be rewritten: **tk\_optionMenu**. This is not expected to be a significant hurdle. # Alternatives 1. Implementing this TIP in Tcl. This would require all widget commands to be wrapped. That's a lot of work compared to the simple C code patch used here. 2. Make a separate **autoname** command, and use this when creating widgets. For example: set frame [frame [autoname .%]] label [autoname $frame.%] > This makes the code a longer and more difficult to read, which is the opposite of what this TIP tries to achieve. 3. A very simple autonaming can be done by just setting aside one global variable and define an alias that increments that variable: set ::# 0 interp alias {} % {} incr ::# set frame [frame .[%]] label $frame.[%] > However, using a short procedure name like "%" has the drawback that extensions or modules which you want to incorporate in your code, may already have defined "%" for something else. Also, as each module may have its own autonaming scheme, there is a risk for overlapping widget names. So auto-naming really belongs in the core. 4. Instead of using a special character, the widget creation commands could get a **-parent** option to define the parent widget. Then, allow the widget command to be called without an explicit widget path, in which case it creates an auto-named child of the parent. The use of **-parent** and an explicit pathname would be mutually exclusive. For example: set frame [frame .f] set button [button -parent $frame -borderwidth 2 ...] > This may create confusion, since it seems to allow the parent to be modified \(after creation\) with the "configure" widget command. Furthermore, to implement this, all widget creation C functions have to be modified, including in extensions such as BLT and tktable, instead of just the NameWindow\(\) function. Probably also the **configure** subcommands have to be adapted... > Another drawback is that "normal" and "automatic" widget creation now have a different syntax. 5. A variation of the previous version can be implemented in pure Tcl: proc newchildof {parent creator args} { (generate proper $child given $parent) $creator $child {*}$args } set frame [frame .f] set button [newchildof $frame button -borderwidth 2 ...] > A drawback of this is that it is a bit verbose, and that "normal" and "automatic" widget creation have a different syntax. Also each extension may use its own autonaming scheme, which does not exactly favor code readability, and may cause name collisions. # Discussion There was a short discussion about this TIP on comp.lang.tcl <http://groups.google.com/group/comp.lang.tcl/browse_frm/thread/2ecd6fbf92de985b/e7471f5829933df2?lnk=gst&q=306#e7471f5829933df2> . Most alternatives which came forth from this discussion, were added to the previous section. While some of the alternative proposals above are usable \(especially **\(5\)**\), they still have drawbacks. The TIP author believes that auto-naming really belongs in the core. Just like in Python and Ruby, auto widget names will probably be the default once they're added to Tk. A good standard syntax for this will not only increase the writability of the code, but also the readability. Indeed, in current Tk code many widget names are used but never referred to again. Just using ".%" on these places makes it clear that the actual widget name is unimportant. Also, the proposed syntax is clear and concise and does not divert from the normal widget creation syntax. # Copyright This document has been placed in the public domain. |
Name change from tip/307.tip to tip/307.md.
|
| < | < | | | | | | | | > | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 307: Make TclTransferResult() Public Author: Erik Leunissen <[email protected]> State: Final Type: Project Tcl-Version: 8.6 Vote: Done Created: 28-Sep-2007 Post-History: Keywords: Tcl, result, transfer, interpreter, API rename ----- # Abstract This TIP proposes to make the existing function **TclTransferResult**\(\) part of the public interface. # Rationale The function **TclTransferResult**\(\) is used by Tcl internally to transfer an interpreter result and/or error information between different Tcl interpreters. Besides its use in the Tcl sources, applications \(based on the Tcl library\) which use multiple interpreters may have a need for this functionality as well. However, programmers are likely to overlook the existing TclTransferResult\(\) as long as the function continues to lead its more or less hidden existence. \(The TIP author discovered its existence only after bugs in his own code led him to inspect how Tcl internally handles result and error info between interpreters.\) Making the function public is very much a matter of courtesy/generosity to programmers that use the Tcl library. It also seems to make the API's for result and error handling more complete. This TIP does not propose to change either the arguments or semantics of the function. # Implementation There is not much to implement: TclTransferResult\(\) already exists in _tclResult.c_. What remains to be done: * renaming to Tcl\_TranferResult\(\): i.e. insert a single underscore character in its name. The function is not declared static already. * slot it into the Tcl stubs table. * write documentation A draft version of the documentation has already been supplied as a separate file _Tcl\_TransferResult.doc_ \(see <http://sf.net/support/tracker.php?aid=1723738> \). It has been written as an addition to an existing man page. The question remains which is the most appropriate manual page to add it to. Considerations for placement of the documentation: * man page for Tcl\_CreateInterp: this is the only manual page that is solely intended for multiple interpreters which are truly arbitrary interpreters, i.e. without any imposed relationship between them. However, it doesn't concern interp results. * man page for Tcl\_CreateSlave: this manual page says for itself that it concerns multiple interpreters, which is only half the truth: it concerns mostly interpreters that have an explicit master-slave relationship, the only exception being Tcl\_CreateAlias\(Obj\). * man page for Tcl\_SaveResult: handles interp results, but is not at all intended for multiple interpreter situations. # Copyright This document has been placed in the public domain. |
Name change from tip/308.tip to tip/308.md.
|
| < | < | | | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | < > | | | | | | < | | > | | | | | | | | | | | | | | | | | | | | | < | > | | | | | | | | | | | < | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 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 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 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 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 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 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 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 | # TIP 308: Tcl Database Connectivity (TDBC) Author: Kevin B. Kenny <[email protected]> Author: Artur Trzewik <[email protected]> Author: Andreas Leitgeb <[email protected]> Author: Donal K. Fellows <[email protected]> State: Final Type: Informative Vote: Done Created: 15-Nov-2007 Post-History: Obsoleted-By: 350 ----- # Abstract This TIP defines a common database access interface for Tcl scripts. # Corrections There are corrections to this TIP in [[350]](350.md) as well. Readers of this document should see that one too. # Introduction There has been a fair amount of discussion, that flares and dies back, regarding the need for a "Tcl database connectivity layer" in the Tcl core. This document specifies what this discussion means. At its present stage of development, it is to be considered very much a draft; discussion is actively solicited. Parties who are interested in a detailed background of this TIP may a more extensive discussion of motivations and objectives in the author's posting to _comp.lang.tcl_ and the _tcl-core_ newsgroup, obtainable from <http://groups.google.com/group/comp.lang.tcl/msg/9351d1b2a59ee2ca> or <http://aspn.activestate.com/ASPN/Mail/Message/tcl-core/3581757> . ## What is Tcl's Database Connectivity Layer? If we look at other database connectivity layers such as ODBC/DAO, JDBC, Perl's DBD/DBI, we find that there really isn't very much, if anything, inside them. Rather than being a body of code, they consist primarily of specifications of the interfaces to which the author of a database connectivity module must conform. The real work of connecting to the databases happens inside the connectivity modules, which are generally speaking under the control of the database teams. In terms of practical politics, there isn't really any other way to do it; the Tcl maintainers are highly unlikely to want to take on the job of connecting to arbitrary database API's. In other languages, such as C\+\+ and Java, it is often necessary to have interface definitions that are understood by a compiler in order to get the "pluggability" of arbitrary database connectivity. In Tcl, however, an "interface" is best understood as an ensemble implementing a predetermined set of commands. There is no counterpart to a Java or C\+\+ interface definition, nor does there need to be. For this reason, the work product of a "Tcl database connectivity" development effort is likely \(at least at the first stage\) to consist primarily of a specification document, perhaps with reference implementations for one or a few popular databases. To be considered "in the core", the specification should be included with the Tcl documentation, and be under control of the TIP process. The database implementations should be considered "extensions," and have their own configuration management. This statement doesn't say that we can't choose from among them a set that we will package with releases of the Tcl core. In fact, I hope that this effort will be one driver for the TCT to sort out the management of "bundled extensions." ## Mechanics of This Document I write this document in "standards committee prose". \(While turgid, it at least is often well-understood; I offer no further defence.\) In particular: * the word "MAY" is construed as allowing a given behaviour but imposing no requirement other than that clients be prepared for it; * the word "MUST" \(and conversely "MUST NOT"\) is construed as requiring a given behaviour; implementations that fail one or more requirements given by "**must**" are non-compliant; * the word "SHOULD" \(and conversely "SHOULD NOT"\) indicates that a given behaviour is expected of an implementation unless there is a compelling reason not to include it; while not formally non-compliant, implementations that fail one or more requirements given by "SHOULD" can be understood to have issues with respect to "quality of implementation." * the future of determination \("SHALL" or "WILL" according to the usual customs of formal written English\) is construed as a promise to which the Tcl Core or the Tcl Core Team, as appropriate, shall adhere. It describes requirements of the Tcl Core, rather than of database connection modules. * the term, "integer value" refers to any string acceptable to **Tcl\_GetBignumFromObj**; the term "native integer value" refers to a value acceptable to **Tcl\_GetIntFromObj**, and hence to a value that can be represented by a C **int** on the target machine. * the term, "boolean value" refers to any string acceptable to **Tcl\_GetBooleanFromObj** and hence includes at least '1', '0', 'on', 'off', 'yes', 'no', 'true', and 'false'. * the term "ensemble" refers to a Tcl command that accepts subcommands. It does not imply that any given command is implemented using the **namespace ensemble** mechanism. # Specification ## Connecting to a Database Obviously the first thing that any connectivity layer has to offer is the ability to select a database. The way databases are named is quite specific to the database manager, as is the way access is negotiated \(credentials such as user name and password may be required, session keys may be negotiated for privacy and authentication, and so on\). All of this machinery is formally out of scope for this specification. Similarly, the machinery of database administration \(at least at the level of creating/deleting entire databases, managing the physical layer, and authorizing clients\) is presumed to be already taken care of. We need merely specify that a connectivity layer must provide at least one command that accepts arguments describing the desired connection and returns a _database handle_ - defined to be an ensemble through which interactions with the given database instance will take place. Here, _database instance_ means the database, or databases, that the given handle can access; rather a circular definition. In many SQL systems, it is possible for a single connection to access several "databases" managed by SQL CREATE DATABASE statments, or several "tablespaces" or similar constructs. We presume that database module implementors will know what is appropriate for their systems, and intentionally leave this particular matter somewhat vague. ## Basic Mechanics of Database Interfaces Database handles are Tcl ensembles, meaning that they are commands that support subcommands. Other ensembles, such as statement handles, are also defined in this specification. Any of the ensembles MAY support abbreviation of its subcommands according to the rules defined by **Tcl\_GetIndexFromObj**; nevertherless, code that uses the database interface SHOULD spell out subcommands in full. Many of the subcommands are expected to take options in Tcl's usual syntax of: > ?_-option_ ?_value_?? ?_-option value_?... In all of the places where this syntax is expected, a database module MAY support abbreviation of options according to the rules of **Tcl\_GetIndexFromObj\(\)**; once again, code that uses the interface SHOULD spell out options in full. All the database objects \(connections, statements and result sets\) are "duck typed" - that is, "If it walks like a duck and quacks like a duck, I would call it a duck. \(James Whitcomb Riley\)." In other words, the ensembles may be implemented using any available functionality as long as the result is that they use the interfaces described. Nevertheless, as a convenience to implementors, a set of base classes, called **tdbc::connection**, **tdbc::statement**, and **tdbc::resultset**, SHALL be provided using Tcl's native object orientation as described in [[257]](257.md). Certain advantages will accrue to database implementors by using these base classes. In particular, the **tdbc::\*** classes SHALL do all the bookkeeping needed to determine what statements and result sets are open, SHALL provide the internal iterators **allrows** and **foreach**, SHALL implement the **transaction** method on connections, and SHALL ensure that the **close** method on the objects functions the same as renaming the object to the null string. ## Configuring a Database Handle Once a handle is returned, there are a number of session-level attributes that may be controllable. Every database handle MUST provide a **configure** subcommand that takes the form: > _dbHandle_ **configure** ?_-option_ ?_value_?? ?_-option value_?... This configuration process is analogous to configuring a Tk widget. If there are no arguments presented to **configure**, the return value MUST be a list of alternating options and values describing the configuration parameters currently in effect. If a single argument is presented, it MUST be the name of a configuration parameter, and the return value MUST be current value for that parameter. Finally, if more than one argument is presented, they MUST be a list of alternating parameter names and values. This last form is an order to set the given parameters to the given values. The connectivity layer SHOULD implement the following parameters, and MAY implement others: \(_Note:_ an earlier draft of this TIP specified a **-autocommit** option; this option has been removed because it is redundant with the transaction management primitives below.\) * **-encoding** _name_ > Requests that the encoding to be used in database communication protocol be changed to the one given by _name_, which MAY be any name acceptable to the [encoding] command. A well-designed database interface SHOULD NOT require this command; however, some backends make it virtually inevitable that mid-stream changes of encodings will be required. * **-isolation** _level_ > Requests that transactions performed on the database be executed at the given isolation _level_. The acceptable values for _level_ are: > \* **readuncommitted** > > Allows the transaction to read "dirty", that is, uncommitted data. This isolation level may compromise data integrity, does not guarantee that foreign keys or uniqueness constraints are satisfied, and in generall does not guarantee data consistency. > \* **readcommitted** > > Forbids the transaction from reading "dirty" data, but does not guarantee repeatable reads; if a transaction reads a row of a database at a given time, there is no guarantee that the same row will be available at a later time in the same transaction. > \* **repeatableread** > > Guarantees that any row of the database, once read, will have the same values for the life of a transaction. Still permits "phantom reads" \(that is, newly-added rows appearing if a table is queried a second time\). > \* **serializable** > > The most restrictive \(and most expensive\) level of transaction isolation. Any query to the database, if repeated, will return precisely the same results for the life of the transaction, exactly as if the transaction is the only user of the database. > \* **readonly** > > Behaves like **serializable** in that the only results visible to the transaction are those that were committed prior to the start of the transaction, but forbids the transaction from modifying the database. > A database that does not implement one of these isolation levels SHOULD instead use the next more restrictive isolation level. If the given level of isolation cannot be obtained, the database interface MUST throw an error reporting the fact. The default isolation level SHOULD be at least **readcommitted**. > A database interface MAY forbid changing the isolation level when a transaction is in progress. * **-timeout** _ms_ > Requests that operations requested on the database SHOULD time out after the given number of milliseconds, if such an option is supported by the underlying connectivity layer. * **-readonly** _boolean_ > Notifies that the application will, or will not, limit its activity to operations that do not modify the content of the database. This option MAY have the effect of adjusting the transaction isolation level. The command that returns a database handle SHOULD also accept these options. ## Transaction Isolation A database handle MUST implement the three subcommands **starttransaction**, **commit** and **rollback**: > _dbHandle_ **starttransaction** Begins an atomic transaction on the database. If the underlying database does not implement atomic transactions or rollback, the **starttransaction** subcommand MUST throw an error reporting the fact. If the underlying database does not implement nested transactions, a **starttransaction** command that is executed when there is a transaction already in progress \(started, but neither committed nor rolled back\) MUST result in an error. > _dbHandle_ **commit** Commits a transaction to the database, making the changes durable. > _dbHandle_ **rollback** Rolls back a transaction against the database, cancelling any changes made during the transaction. Statements executed against the database when no transaction is in progress \(before the first **starttransaction** or after all started transactions have been either committed or rolled back\) SHOULD be _auto-committed_; that is, each such statement SHOULD be executed as if a **starttransaction** command preceded the statement and a **commit** command followed it \(assuming that the statement succeeded; errors should result in **rollback** of course\). These commands are provided primarily to support the construction of higher-level operations. In particular, most simple transactions against a database can be handled using the **transaction** command: > _dbHandle_ **transaction** _script_ Executes the given _script_ with transaction isolation. In this command, the _dbHandle_ argument is a handle to a database connection, and the _script_ argument is a Tcl script to be evaluated in the calling scope. The script is treated as a single atomic database transaction. The **starttransaction** command is executed against the given database connection, and then the _script_ is evaluated. If it completes successfully \(_TCL\_OK_\), the transaction SHALL be committed to the database. If it fails, \(_TCL\_ERROR_\), the transaction SHALL be rolled back and not visible to other users of the database. _TCL\_BREAK_, _TCL\_CONTINUE_ and _TCL\_RETURN_ SHALL result in a commit and subsequently rethrow the same exception status outside the transaction. Exception status codes other than these five SHALL rollback the transaction and be rethrown. \(_Note:_ Scripts inside a **transaction** command SHOULD avoid use of the **return -code** or **return -level** operations. If a script returns from a transaction, with any combination of return options, the transaction SHALL be committed.\) Just as with **starttransaction**, if a [_dbHandle_ **transaction**] command is executed while another transaction is already in progress, it is requesting nested transaction semantics. A database handle to an engine that supports nested transactions MUST treat this case correctly; a database handle to an engine that does not support nested transactions \(including one that does not support transactions at all\) MUST throw an error. The **transaction** subcommand SHALL be provided by the **tdbc::connection** base class; database interfaces that use the TclOO features and the TDBC base classes do not need to implement it. ## Closing a Database Connection A database handle MUST implement the command: > _dbHandle_ **close** This command MUST dismiss the connection to the database and is expected to clean up the system resources associated with it. If there is an uncommitted transaction, it SHOULD be rolled back. Any handles to other objects associated with the database SHOULD become invalid. A database interface also SHOULD perform the same actions if a handle is deleted by means of the **rename** command. \(Interfaces that are implemented in Tcl may be notified of this action by creating a deletion trace with **trace add command**.\) It is recognized that command deletion traces present difficulties in situations like namespace and interpreter deletion; the **close** subcommand shall therefore be considered the preferred way to terminate connections. A database interface SHOULD attempt to arrange, if possible, to rollback unfinished transactions and clean up on process exit. In particular, if the underlying database engine supports transactions, it SHOULD be considered an error to commit any work that remains uncommitted on process exit. The **close** command SHALL be provided by the **tdbc::connection** base class; database interfaces that use the TDBC base classes do not need to implement it. The base class implementation destroys the object using **my destroy**. As a result, any statements obtained from the connection are also destroyed, since they are stored in a namespace that is subordinate to the connection's namespace. The destructor of the connection object is expected to close the underlying database connection and release any system resources associated with it. ## Preparing Statements A database handle must support the **prepare** command, which has the syntax: > _dbHandle_ **prepare** _SQL-code_ The _SQL-code_ argument is a SQL statement that is to be executed against the given database connection. This command does not execute the statement directly; rather, it prepares to execute the statement, possibly performing tasks such as code compilation and query optimisation. The database interface MUST support substitutions in _SQL-code_. Each substitution request has the form _:variableName_. That is, each substitution request begins with a literal colon \(:\), followed by a letter or underscore, followed by zero or more letters, digits, or underscores. The database interface is responsible for translating from this syntax to whatever the underlying engine requires. Typical strings required in database interfaces are _:name_, _:number_, _@name_, _@number_, and _?_. The return value from the **prepare** command is a _statement handle_, discussed under "The statement interface" below. _Rationale._ The choice of the colon deserves some discussion. It would surely be more natural for Tcl to use a literal dollar sign to introduce a variable name. This choice, however, seems unwise, since several databases \(most notably Oracle\) allow the use of table and view names that contain dollar signs. While it might be possible to continue to use these while allowing for variable substitution \(for instance, by mandating that table or view names with dollar signs be enclosed in double quotes\), it seems unnatural. The colon is syntax that is recognized by JDBC, ODBC, and Oracle's native API, and as such will be familiar to most SQL programmers and unlikely to collide with native syntax. The requirement to support prepared statements is intended to guard against SQL insertion attacks. An interface to a database whose native API does not support prepared statements MUST simulate them. In particular, when the **execute** command is executed on a statement, substitution must be performed in a safe fashion with whatever magic quoting is required. In any case, magic quoting should be regarded as an infelicitous expedient and avoided if at all possible. If a database interface uses the **tdbc::connection** base class, then a **prepare** method will be provided for it. If this method is not overridden, then the database interface MUST arrange that the constructor of the connection sets the instance variable, _statementClass_, to the fully qualified name of the command that constructs statements. The **prepare** method SHALL invoke that command with a call of the form: > _statementClass_ **create** _handle_ _connectionHandle_ _sql_ where _handle_ is the name of the new statement being created, _connectionHandle_ is the handle to the connection creating it, and _sql_ is the SQL statement being prepared. ## Stored Procedure Calls A second way to prepare statements is to prepare a stored procedure call. If a database interface supports stored procedures, it MUST support the **preparecall** command: > _dbHandle_ **preparecall** _call_ _call_ is a string that describes a call to a stored procedure. It takes the form: > ?_:varName_ **=**? _procName_ **\(** ?_:varName_? ?**,** _varName_?... **\)** The result of the **preparecall** command is a statement handle. The statement handle may be used just as any other statement handle. The **preparecall** method SHALL _not_ be provided in the **tdbc::connection** base class; individual database interfaces are expected to do so. They MAY do so by rewriting the call to whatever syntax the native database requires, and delegating to the **prepare** method to prepare that, or they MAY instead prepare another ensemble. \(See "The TDBC base classes" below for details of integrating this mechanism with the base classes.\) ## Quasi-Direct Execution A database handle MUST support the following two calls: > _dbHandle_ **allrows** ?**-as** _lists_\|_dicts_? ?**-columnsvariable** _varName_? ?**--**? _sql_ ?_dictionary_? This command prepares the SQL statement given by the _sql_ parameter, and immediately executes it. Variable substitutions inside the _sql_ parameter are satisfied from the given _dictionary_, if one is supplied, and from variables in the caller's scope otherwise. The **-as** option determines the form of the result, and the **-columnsvariable** option provides an optional variable in which the names of the result columns will be stored. Upon termination of the command, whether successful or unsuccessful, the prepared statement is closed. The command returns a list of the rows returned by the affected statement. \(If the affected statement does not yield a set of rows, the return value from the _allrows_ command is an empty list.\) This command MUST function the same way as preparing the statement explicitly, executing the **statement allrows** call \(see below\) on the resulting statement handle, and then \(irrespective of whether the operation succeeeded\) destroying the statement handle. > _dbHandle_ **foreach**?**-as** _lists_\|_dicts_? ?**-columnsvariable** _varName_? ?**--**? _sql_ ?_dictionary_? _varName_ _script_ This command prepares the SQL statement given by the _sql_ parameter, and immediately executes it. Variable substitutions inside the _sql_ parameter are satisfied from the given _dictionary_, if one is supplied, and from variables in the caller's scope otherwise. The **-as** option determines the form of the result, and the **-columnsvariable** option provides an optional variable in which the names of the result columns will be stored. For each row returned by the given statement, the given _varName_ is set to a list or dictionary containing the returned row, and the given _script_ is executed in the caller's scope. Upon termination of the command, whether successful or unsuccessful, the prepared statement is closed. This command MUST function the same way as preparing the statement explicitly and then executing the _statement_ **foreach** call on the resulting statement handle. Both of these commands SHALL be provided in the **tdbc::connection** base class. ## Introspecting the Sets of Handles A database handle MUST support the **statements** command: > _dbHandle_ **statements** This command MUST return a list of the statements that have been prepared by means of [_dbHandle_ **prepare**] but not yet dismissed using [_statementHandle_ **close**]. Likewise, a database handle MUST support the **resultsets** command: > _dbHandle_ **resultsets** This command MUST return a list of the result sets that have been returned \(by executing statements, or by querying metadata\) and have not yet been dismissed using [_resultSetHandle_ **close**]. Both of these commands SHALL be provided in the _tdbc::connection_ base class. Using the base class implementations imposes certain restrictions on derived classes. \(See "The TDBC base classes" below for details of integrating this mechanism with the base classes.\) ## Querying Metadata A database interface MUST provide a way of enumerating the tables in the database. The syntax for querying tables MUST be: > _dbHandle_ **tables** ?_matchPattern_? The optional argument _matchPattern_, if supplied, is a pattern against which the table names are to be matched. The database interface MUST recognize the SQL wildcards **%** and **\_** in the pattern. A database interface MUST provide a way of enumerating the columns in a database table. The syntax for querying columns MUST be: > _dbHandle_ **columns** _tableName_ _?matchPattern?_ The return value from the **tables** and **columns** commands MUST be a dictionary. The keys of the dictionary MUST be the names of the tables in the database, or respectively the columns in the given table. The values stored in the dictionary returned from the **tables** command MUST be dictionaries. The keys and values of these dictionaries, nevertheless, are implementation-defined; only the keys are mandated in this specification. The values stored in the dictionary returned from the **columns** command MUST themselves be dictionaries. These subdictionaries MUST include the keys, **type**, **precision**, **scale**, and **nullable**. The **type** value MUST be the data type of the column, and SHOULD be chosen from among the standard types _bigint_, _binary_, _bit_, _char_, _date_, _decimal_, _double_, _float_, _integer_, _longvarbinary_, _longvarchar_, _numeric_, _real_, _time_, _timestamp_, _smallint_, _tinyint_, _varbinary_, and _varchar'. The **precision** and **scale** values SHOULD give the precision and scale of the column, and the **nullable** value SHOULD give a boolean value that represents whether the given column can contain NULL values. Other keys MAY be included in the subdictionaries returned from **tables** and **columns**, and SHALL be added to this document \(as optional columns\) on request from the implementors of database interfaces. ## The Statement Interface The statement handle returned from the **prepare** command on a database interface must itself be an ensemble. The following subcommands MUST be accepted: > _statementHandle_ **params** Requests a description of the names and expected data types of the parameters to the given statement. The return value from the **params** command MUST be a dictionary whose keys are the names of the parameters and whose values are themselves dictionaries. The keys of the subdictionaries MUST include _name_, _type_, _precision_, _scale_, and _nullable_. They are interpreted in the same way as those of the **columns** subcommand to a database interface \(shown above\). The subdictionaries also MUST include the key, _direction_, whose value identifies the direction of parameter transmission, and MUST be chosen from among _in_, _out_ and _inout_. > _statementHandle_ **execute** ?_dictionary_? Executes a statement against a database. Any variable substitution present in the SQL that was provided when the statement was created MUST be performed at this time. The variable values MUST be obtained from the given _dictionary_, if one is supplied. If the dictionary does not contain a key equal to a variable name in the statement, a NULL value MUST be provided. If the _dictionary_ argument is omitted, the variable values MUST be obtained from the scope in which the **execute** command was evaluated. Any variable that is undefined in that scope must be replaced with a _NULL_ value. An array variable provided to a substituent MUST result in an error. Read traces against the substituted variables SHOULD fire, in left-to-right order as they appeared in the SQL statement. The result of the **execute** command SHOULD be a result set, as defined under "The result set interface" below. This method is provided by the **tdbc::connection** base class. In the base class, it works by creating an instance of the class whose name appears in the **statementClass** instance variable. See "The TDBC base classes" below for the details of how the derived classes should be implemented to avail themselves of this method. > _statementHandle_ **close** Announces that a statement is no longer required, and frees all system resources associated with it. The **close** command MAY invalidate any result sets that were obtained by the **params** and **execute** commands. As with database connections, the database interface SHOULD also clean up if a statement handle is removed with _[rename $statement {}]_. Once again, it is recognized that the strange side effects of namespace and interpreter deletion may make this cleanup impossible in some interfaces, so **close** SHALL be considered the standard means of discarding statements. The _close_ command SHALL be provided in the _tdbc::statement_ base class. Database interfaces that use the TDBC base classes do not need to implement it. The base class implementation destroys the object using **my destroy**. As a result, any result sets obtained from the statement are also destroyed, since they are stored in a namespace that is subordinate to the statement's namespace. The destructor of the statement object is expected to release any system resources associated with it. ### Data Types of Parameters to Prepared Statements The syntax described so far presumes that the database interface can determine the expected types of the variables that appear in a prepared statement, or at the very least can accept some sort of variant type and perform automatic type coercion. This requirement does not seem horribly onerous at first inspection, since SQLite allows for "everything is a string" parameters; ODBC offers parameter introspection via the _SQLDescribeParam_ call; and JDBC offers it via the _getParameterMetaData_ method of the _PreparedStatement_ interface. Nevertheless, a deeper examination discovers that in at least ODBC, a driver is allowed to fail to offer _SQLDescribeParam_. Inspection of the JDBC-ODBC bridge reveals that in this case, JDBC will return a _ParameterMetaData_ object that throws a _SQLException_ on any attempt to query specific data. The result is that, while the APIs to introspect parameter types are available, they may be unusable against a particular database engine. In these cases, a backup is needed. For this reason, a database interface MUST support allowing the user to specify types of the parameters of a prepared statement. The syntax for doing so MUST be: > _statementHandle_ **paramtype** _paramName_ ?_direction_? _type_ ?_precision_? ?_scale_? Defines that the parameter identified by _paramName_ in the given statement is to be of type _type_. The _type_ MUST be chosen from among the names _bigint_, _binary_, _bit_, _char_, _date_, _decimal_, _double_, _float_, _integer_, _longvarbinary_, _longvarchar_, _numeric_, _real_, _time_, _timestamp_, _smallint_, _tinyint_, _varbinary_, and _varchar_. \(_Rationale:_ These types appear to suffice for ODBC, and we can always come back and extend them later if needed.\) The _precision_ of a parameter defines the number of characters or digits that it requires, and its _scale_ defines the number of digits after the decimal point, if neeeded. A database interface MAY allow negative numbers for _scale_ in contexts where they make sense. For example, a _scale_ of -3, if allowed, SHOULD indicate that quantities in the given column are all multiples of 1000. The _precision_ and _scale_ are not required by all types. A _direction_ must be one of the words, **in**, **out** or **inout**. It specifies that the given parameter is an input to the statement, an output from the statement, or both. It is usually meaningful only in stored procedure calls. Default is **in**, unless the parameter appears on the left-hand side of an equal side in a stored procedure call, in which case the default is **out**. ### ~Examples $statement paramtype name varchar 40 $statement paramtype balance in decimal 10 2 $statement paramtype transactionDate timestamp Implementors of database APIs SHOULD make every effort to do appropriate type introspection so that programmers can avoid needing to include explicit type information in their SQL statements. ### Internal Iterators A statement handle MUST support the following two calls: > _statement_ **allrows** ?**-as** _lists_\|_dicts_? ?**-columnsvariable** _varName_? ?**--**? ?_dictionary_? This command executes the given _statement_. Variable substitutions inside the statement are satisfied from the given _dictionary_, if one is supplied, and from variables in the caller's scope otherwise. The **-as** option determines the form of the result, and the **-columnsvariable** option provides an optional variable in which the names of the result columns will be stored. Upon termination of the command, whether successful or unsuccessful, the prepared statement is closed. The command returns a list of the rows returned by the affected statement. \(If the affected statement does not yield a set of rows, the return value from the _allrows_ command is an empty list.\) This command MUST function the same way as executing the statement explicitly \(with the given _dictionary_ argument if one is supplied\), executing the _resultset_ **allrows** call \(see below\) on the resulting result set, and then \(irrespective of whether the operation succeeeded\) destroying the result set. > _statement_ **foreach**?**-as** _lists_\|_dicts_? ?**-columnsvariable** _varName_? ?**--**? ?_dictionary_? _varName_ _script_ This command executes the given _statement_. Variable substitutions inside the statement are satisfied from the given _dictionary_, if one is supplied, and from variables in the caller's scope otherwise. The **-as** option determines the form of the result, and the **-columnsvariable** option provides an optional variable in which the names of the result columns will be stored. For each row in the result set, the given _varName_ is set to a list or dictionary containing the returned row, and the given _script_ is executed in the caller's scope. Upon termination of the command, whether successful or unsuccessful, the result set is closed. This command MUST function the same way as executing the statement explicitly, executing the _resultset_ **foreach** call on the resulting statement handle, and then \(irrespective of whether the operation succeeded\) closing the result set. Both of these commands SHALL be provided in the **tdbc::statement** base class. ## The Result Set Interface Result sets represent the results of operations performed on the database. A preferred implementation for large result sets is that they be implemented as database cursors, so that it is possible to iterate over result sets that will not fit in memory. A result set MUST be an ensemble. The following subcommands MUST be accepted: > _resultSetHandle_ **rowcount** Determines the number of rows affected by a SQL statement such as **INSERT**, **DELETE** or **UPDATE**. This count MUST be returned as an integer. It should not be confused with the number of rows in the result set. A database interface need not provide any interface to determine the latter number \(often, the only way to determine it is to read all the rows\). For this reason, the **rowcount** command MAY return an empty string, or a non-positive number, for **SELECT** operations \(and any other operations that do not modify rows of the database\). > _resultSetHandle_ **columns** Determines the set of columns contained in the result set. The set of columns is returned simply as a list of column names, in the order in which they appear in the results. > _resultSetHandle_ **nextrow** ?**-as** **lists\|dicts**? ?**--**? _variableName_ \(This interface SHALL be provided by the **tdbc::resultset** base class. The default implementation SHALL delegate to either the **nextlist** or **nextdict** methods, below. Fetches a row of data from the result set and stores it in the given variable in the caller's context. If **-as dicts** is specified \(the default\), the row MUST be represented as a dictionary suitable for use with the **dict** command. The keys in the dictionary SHALL be the column names, and the values SHALL be the values of the cells. If no rows remain, the **nextrow_ command MUST store an empty dictionary. If a cell in the row is NULL, the key MUST be omitted from the dictionary. A database interface MUST NOT use a special value of any kind to represent a NULL in a dictionary. If **-as lists** is specified, the row MUST be represented as a list of values, in the order in which they appear in the query. \(If the statement is a stored procedure call, the values comprise all the **out** or **inout** parameters.\) If no rows remain, the **nextrow** command MUST store an empty list. If a cell in the row is NULL, an empty string MUST be stored as its value. The return value of _nextrow_ MUST be 1 if a row has been returned, and 0 if no rows remain in the result set. In the result set, values of type _bigint_, _bit_, _decimal_, _double_, _float_, _integer_, _numeric_, _real_, _smallint_, and _tinyint_ MUST receive their natural representation as decimal numbers. Ideally, they should be returned as "pure" numbers with their string representations generated only on demand. Values of type _char_, _longvarchar_ and _varchar_ MUST be returned as Tcl strings. _A database interface implemented in C _MUST_ take care that all strings are well-formed UTF-8._ Values of type _date_ and _timestamp_ MUST be returned as a numeric count of seconds from the Tcl epoch; if necessary, this count may have a decimal point and an appropriate number of additional decimal places appended to it. Values of type _time_ MUST be returned as a integer count of seconds since midnight, to which MAY be appended a decimal point and a fraction of a second. Values of type _binary_, _longvarbinary_ and _varbinary_ MUST be returned as Tcl byte arrays. _Rationale:_ Dictionaries and lists are both useful in representing the result set rows. Dictionaries allow for a ready distinction between NULL values in a database and any other string. With any scheme where values that can include NULLs can appear in Tcl objects, the problem arises that NULL must be distinguished from any other string, particularly including the empty string and the word "NULL". The lack of such a distinction has led to several ill-advised proposals, such as [[185]](185.md), for representing NULLs in Tcl. These alternatives founder on the principle of "everything is a string". The NULL value is not any string. Dictionaries also have the advantage that results can be addressed by name rather than by position. On the other hand, lists are convenient when formatting tabular results from _ad hoc_ queries. The brevity of code that can be achieved with them is also attractive. For this reason, this TIP requires both formats to be made available. > _resultSetHandle_ **nextdict** _variableName_ > _resultSetHandle_ **nextlist** _variableName_ These two calls are precisely equivalent to calls to the **nextrow** command with the **-as dicts** and **-as lists** option respectively. A database interface MUST provide both of these, and they are the fundamental means for retrieving rows from the result set. > _resultSetHandle_ **close** Dismisses a result set and releases any system resources associated with it. As with statements and database connections, the database interface SHOULD also clean up if a resut set handle is removed with _[rename $statement \{\}]_. Once again, it is recognized that the strange side effects of namespace and interpreter deletion may make this cleanup impossible in some interfaces, so **close** SHALL be considered the standard means of discarding result sets. The **close** command SHALL be provided by the **tdbc::resultset** base class. The base class implementation destroys the object using **my destroy**. The destructor of the result object is expected to release any system resources associated with it. ### Internal Iterators A result set handle MUST support the following two calls: > _resultset_ **allrows** ?**-as** _lists_\|_dicts_? ?**-columnsvariable** _varName_ ?**--**? This command executes the **nextrow** command repeatedly, producing a list of dictonaries or of lists \(according to the value of the **-as** option\). The **allrows**command returns the resulting list. Optionally, the names of the columns of the result set are also stored in the named variable given by the **-columnsvariable** option. > _statement_ **foreach**?**-as** _lists_\|_dicts_? ?**-columnsvariable** _varName_? ?**--**? _varName_ _script_ This command optionally stores the names of the columns of the result set in the variable designated by the **-columnsvariable** option. It then executes the **nextrow** command repeatedly until all rows of the result set have been processed. The **nextrow** command receives the given **varName** and **-as** option, and stores the row in the named variable. For each row processed, the given **script** is executed in the caller's scope. Both of these commands SHALL be provided in the **tdbc::resultset** base class. ## The TDBC Base Classes Most implementations of database drivers SHOULD, as mentioned before, use Tcl objects \(as in [[257]](257.md)\) that inherit from the **tdbc::connection**, **tdbc::statement** and **tdbc::resultset** classes. The foregoing discussion has described the user-visible methods that are provided by doing so \(and must otherwise be implemented\). This section is directed to the driver implementor, and discusses certain necessary housekeeping issues. ### Database Connections However a database connection object is constructed, its constructor will need to seize resources \(such as opening a database connection to the underlying database system\). If the bookkeeping done by the base classes is to work correctly, initialization of the **tdbc::connection** base class needs to happen before external resources are seized. In addition, if the **prepare** method is not overloaded \(and the driver SHOULD NOT have to overload it\), the name of the class that implemements the statement interface needs to be provided at this time. The recommended sequence for connection construction is: constructor args { next; # Initialize tdbc::connection my variable statementClass set statementClass ::whatever;# Tell tdbc::connection what # class must be instantiated by # the 'prepare' method my init {*}$args # Perform implementation-specific # initialization } Some database interfaces have a different API to stored procedures than to ordinary SQL statements. These databases may need a separate type of statement object from the one that implements ordinary statements. This object can be managed as a statement owned by the connection by using a **prepareCall** method that looks like: method prepareCall {call} { my variable statementSeq; # Provided in the # tdbc::connection base class return [preparedStatementClass create \ Stmt::[incr statementSeq] [self] $call] } In this call, **preparedStatementClass** is the name of the class that implements prepared statements. Its constructor is expected to accept two arguments: the handle to the database connection, and the prepared statement that was passed to prepareCall. Placing the resulting object inside the **Stmt** namespace under the current object \(this namespace is created by the constructor of **tdbc::connection**\) allows for its destruction to be sequenced correctly when the connection is destroyed. The methods that a derived class from **tdbc::connection** MUST implement are **prepareCall**, **begintransaction**, **commit**, and **rollback**. In addition, system resources belonging to the connection itself MUST be cleaned up by a destructor or by a deletion callback at C level. \(Statements and result sets MUST not be deleted then; the base classes take care of that.\) See "Best practices for memory management" below for further discussion. ### Statements The class that implements a statement SHOULD normally inherit from the **tdbc::statement** base class. Its constructor accepts the connection handle and the SQL statement to prepare. The constructor is responsible for invoking the base class constructor with **next**, setting an instance variable _resultSetClass_ to the name of the class that implements its result set, and then preparing the statement. \(The constructor is invoked by the **prepare** method of **tdbc::connection.\) A sample constructor looks like: constructor {connection sql} { next; # initialize the base class my variable resultSetClass set resultSetClass whatever; # Tell the base class what class # to use for result sets my init $connection $sql; # The [[init]] method should do # whatever is necessary to prepare # the statement } Derived classes from **tdbc::statement** MUST also implement the **params** and **paramtype** methods. In addition, system resources belonging to the statement itself MUST be cleaned up by a destructor or by a deletion callback at C level. \(Result sets MUST not be deleted then; the base classes take care of that.\) See "Best practices for memory management" below for further discussion. ### Result Sets The class that implements a result set SHOULD normally inherit from the **tdbc::resultset** base class. Its constructor accepts the statement handle and the arguments to the **execute** method. The constructor is responsible for invoking the base class constructor with **next**, and executing the statement. A sample constructor looks like: constructor {statement args} { next uplevel 1 [list {*}[namespace code {my init}] $statement {*}$args] } Note the peculiar form of invocation for the **init** method in the example above. Since the **init** method needs access to local variables in the caller's context to do variable substitution, it needs to be executed at the same stack level as the constructor itself. The [namespace code {my init}] call gives a command prefix that can be used to invoke the method in a foreign context, and this command is then executed with [uplevel 1] to do the initialization. Besides the constructor and **init**, the other methods that a result set class MUST implement are **columns**, **nextrow**, and **rowcount**. In addition, a destructor \(or a C deletion callback\) MUST clean up any system resources belonging to the result set. ### Best Practices for Memory Management in Database Interfaces Since the TclOO interfaces are so new, it seems wise to give developers of database interfaces written in C some guidance about effective ways to manage memory. A C-level extension, if written correctly, gets considerable assistance in releasing memory at the appropriate times from TclOO and the tdbc base classes. When a database interface is first loaded as an extension, it is entered through its _PackageName_\_**Init** function. It will call, in order, **Tcl\_InitStubs**, **Tcloo\_InitStubs**, and **Tdbc\_InitStubs** so that Tcl, the TclOO system, and the TDBC base classes are all available. Its next task is to allocate any per-interpreter data that may be required. \(In the case of the **tdbc::odbc** bridge, the per-interpreter data include an ODBC environment handle and a string literal pool.\) The per-interpreter data structure SHOULD be reference counted, since the order of destruction of the objects that refer to it is unpredictable. Next, the initialization function creates the classes, usually by evaluating an initialization script containing a call to **tcl\_findLibrary**, where the Tcl code contains the skeletons of the class definitions. With the class definitions in hand, methods that are implemented in C can be attached to them. Any methods that need the per-interpreter data can receive it as ClientData. The reference count of the per-interpreter data SHOULD be incremented for these, and the method delete procedures should be responsible for decrementing the reference count. Each of the three classes that make up a database interface SHOULD have a reference-counted data structure to hold any instance data. This structure SHOULD be created within the **init** method, and attached to the object with **Tcl\_ObjectSetMetadata**. The metadata type structure SHOULD designate a delete procedure that decrements the reference count. The type structure MAY designate a clone procedure that returns **TCL\_ERROR**; it is entirely permissible for TDBC objects not to be clonable. Generally speaking, each object's instance data structure will contain a pointer to \(and hold a counted reference to\) the next higher object in the ownership hierarchy. A result set will refer to the statement that produced it; a statement will refer to the connection in which it executes, and a connection will refer to the per-interp data. With this infrastructure in place, object destruction becomes strictly a local matter. Any object, when its reference count becomes zero, MUST release any system resources that belong to it, and decrement the reference count of the next object up. There is no need for a connection to track its statements, or a statement to track its result sets. This happens automatically because the **prepare** and **execute** methods create statements in a namespace subordinate to the namespace of the owning connection, and create result sets in a namespace subordinate to that of the owning statement. When the owning objects are destroyed, the subordinate namespaces are also destroyed, invoking the destructors of the objects within them. This whole scheme is simpler than it sounds, and is observed to work well for the **tdbc::odbc** bridge \(see the source code of the bridge for further details\). Closing a connection gracefully deletes the statement and result class objects \(in Tcl\) from top to bottom, and then deletes the corresponding C data structures from bottom to top, finally cleaning up the connection data itself. Note that, since TclOO does not guarantee to run destructors on **exit**, if a database interface needs to always close the underlying connection on termination, the implementation code should install an exit handler with **Tcl\_CreateExitHandler** if it needs to. ## Support Procedures for Implementors of Database Interfaces In addition to the convenience commands discussed above, the Tcl system SHALL provide certain commands to aid the job of database implementors. ### SQL Tokenisation The task of mapping variable substituions in the form, **:varName** into whatever form that a native database API can handle is a somewhat tricky one. For instance, substitutions that appear inside quoted strings MUST NOT be mapped. In order to aid in this task, the Tcl system SHALL provide a command, **::tdbc::tokenize**. This command SHALL accept a SQL statement as its sole parameter, and return a list of tokens. The lexical value of the tokens can be distinguished by their first characters: * '$', ':' and '@' are all variable substitutions; the remainder of the token string is a variable name. * ';' is a statement separator, for databases that allow multiple statements to be prepared together. * '-' is a comment * Anything else is literal text to be copied into a SQL statement. Assuming that a native database's lexical structure conforms with standard SQL, the variable names can be substituted with parameter numbers, question marks, or whatever the database needs, to yield the native SQL that must be prepared. Tokenisation is also available at the C level; to access it, a C extension MUST first call **Tdbc\_InitStubs**; it is a macro that behaves as if it is a function with the type signature > int **Tdbc\_InitStubs**\(Tcl\_Interp \*_interp_\); where _interp_ is a Tcl interpreter. The function returns **TCL\_OK** if successful, and **TCL\_ERROR** \(with an error message left in the interpreter\) in the case of failure. The tokenisation is then available by calling > Tcl\_Obj \***Tdbc\_TokenizeSql**\(Tcl\_Interp \*_interp_, const char *_sqlCode_\); In this call, _interp_ is a Tcl interpreter, and _sqlCode_ is a SQL statement to parse. If the parse is successful, the return value is a Tcl object with a reference count of zero that contains a list of token strings as with the **tdbc::tokenize_ call. # References This specification is largely built from studying existing cross-platform database APIs and deriving a comon set of requirements from them. These include both popular offerings in lower-level languages \(ODBC and JDBC\) and Tcl-level ones \(notably the 'nstcl-database' package, the SQLite API and tclodbc\). "ODBC Programmer's Reference." Redmond, Wash.: Microsoft Corporation, 2007. <http://msdn2.microsoft.com/library/ms714177.aspx> . "Java Platform Standard Edition 6 API Specification." Santa Clara, Calif.: Sun Microsystems, 2007 <http://java.sun.com/javase/6/docs/api/> ; in particular the package named, **java.sql**. Cleverly, Michael. "nstcl-database Package." <http://nstcl.sourceforge.net/docs/nstcl-database/> . Hipp, D. Richard. "The Tcl interface to the Sqlite library." <http://www.sqlite.org/tclsqlite.html> . Nurmi, Roy. "Tclodbc v 2.3 Reference." Available as part of the Tclodbc distribution at <http://sourceforge.net/projects/tclodbc/> , in the file, **DOC/REFERENC.HTM**. # License This file is explicitly released to the public domain and the author explicitly disclaims all rights under copyright law. ---- # Appendix. Additional Possibilities. An earlier version of this TIP specified several more requirements for the TDBC statement objects. In the current version, these requirements have been lifted. The three areas that have been removed are batch processing, asynchronous query handling, and references to cursors. _Rationale:_ Specifying an interface like this one is always a tradeoff between capability of the interface and burden upon the implementors. The earlier requirement for handling these three areas seems improvident. The handling of bulk data \("batch processing"\) is to a large extent a performance issue. In most cases, if the performance of bulk data handling is critical, an implementor will resort to a compiled language rather than to Tcl to do so. The reporting of errors on bulk operations is complicated, as is the specification of what will happen if certain parameter sets succeed while others fail. The benefit of bulk data handling at the Tcl level was not deemed adequate to justify the implementation complexity. The handling of asynchronous queries is also chiefly a performance issue in that it is intended to enable keeping a GUI live while long-running database operations are in progress. This "keep the GUI alive during long operations" requirement is equally well satisfied by performing database operations in a separate thread \(for a thread-enabled Tcl\) or a separate subprocess, and these techniques are familiar to Tcl programmers. For similar reasons, the ODBC manual now formally deprecates using ODBC's asynchronous operations on operating systems that support multithreading. Again, the benefits of integrating TDBC into the event loop do not appear to justify the cost in complexity to be gained. References to cursors are a feature that is highly dependent on the underlying database. It is not clear that the specification described below is even readily implementable on all the platforms that have refcursors. Most of these, in any case, provide some other way of achieving the same end. For instance, Oracle allows returning a cursor by name, and then executing a statment, "FETCH ALL FROM :cursorName", to retrieve the data from the cursor. Again, here is a feature that adds complexity out of proportion to the benefits achieved. ## Batch Processing Some databases provide an interface to pass bulk data into a statement, in order to provide an efficient means for doing tasks such as inserting a large number of rows into a table at once. A statement handle MUST provide the subcommands: > _statement_ **startbatch** Prepares to perform batch processing on the specified statement. > _statement_ **addtobatch** _dictionary_ Adds the values given by _dictionary_ into the specified statement. The _dictionary_ argument is exactly the same as the _dictionary_ argument to [_statement_ **execute**]. If no batch operation is in progress, the database interface MUST throw an error. > _statement_ **executebatch** Executes the batch of operations accumulated by [_statement_ **addToBatch**]. The result of **executebatch** MUST be a result set. The rows of the result set are the result of concatenating the rows returned from the individual operations. If no batch operation is in progress, the database interface MUST return an error. If an underlying database does not support batch operations, the database interface SHOULD simulate them by accumulating the data in memory and executing the statement repeatedly when the **executeBatch** operation is requested. The database interface MUST return an error if an attempt is made to execute a statement in the ordinary manner or to request a commit while there is an unfinished batch in progress. A rollback, or closing the statement, or closing the database connection, while a batch is in progress MUST result in abandoning the batch without applying any changes to the database. ## Asynchronous Queries Some database operations take a long time to complete. In order to avoid freezing the event loop, a database interface MAY provide an asynchronous query mechanism. If it does so, it MUST take the form: > _resultSet_ **whenready** _script_ In this interface, _resultSet_ is the handle of a result set. The **whenready** command requests that _script_ be evaluated at the global level once for each row of the result set, plus once after all rows have been returned. The script SHOULD execute **nextrow** to retrieve the next row or get the indication that no rows remain. ## References to Cursors Some databases allow stored procedures to return references to cursors. If a column of a result set contains a reference to a cursor, it MUST be represented in Tcl as another result set handle. A Tcl script can then iterate over this included result set to use the reference to a cursor. The given result set MUST be destroyed upon the next call to _nextrow_. For this reason, Tcl code MUST not use the **allrows** command with a statement that can return references to cursors. ---- # Appendix. Change Summary 2008-04-27: Removed asynchronous queries, refcursors, and batch updates from the main body of the spec. Performed a good bit of general cleanup to bring the spec back in line with the reference implementation being developed. 2007-11-23: Expanded transaction management to have both the **transaction** command and explicit transaction boundaries. Added transaction isolation levels. > Added lists as an alternative to dicts as a representation of rows in result sets. Added a side interface for retrieving the set of column names in the convenience procedures. > Simplified introspection to return lists instead of result sets |
︙ | ︙ | |||
1242 1243 1244 1245 1246 1247 1248 | > Added reference to the author's cover letter on tcl-core. > Added missing citation of the nstcl-database API. ---- | | | | | | | | | | | > | 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 | > Added reference to the author's cover letter on tcl-core. > Added missing citation of the nstcl-database API. ---- # Appendix. Comments Artur Trzewik \(2007-11-19\): > I miss defined error handling. Current DB-Api handles them in different way. How to obtain SQL-error message from server. If "execute" fails should it return TCL\_ERROR or it should be special api for error code. > I miss C-framework or template to implement such API. Writing everything from scratch for all DB will be quite painfully. There are many things which can be reused: New Tcl objects, handles managing, thread-safe managing, encoding. Also prepared statements are not so easy. For example mysql requires that one allocate fixed size memory for all variables. It does not fit well with Tcl. Kevin Kenny \(2007-11-23\): > Rest assured that at least one reference implementation will be published before this TIP is considered FINAL; database implementors are not going to be abandoned. Andreas Leitgeb \(2008-06-17\): > For **allrows** and **foreach** calls, there has been some discussion about replacing the idiom **-as list\|dict** by separate methods. Was this discussion dropped, or has it just not yet been reflected here? > For **allrows** and **foreach** calls there is ?**-columnsvariable** _varName_? ... I think, another option: ?**-indicatorvariable** _varName_? would be useful, as it allows both NULLs and equally named columns at the same time. Without indicator, dicts can handle only the former, and lists only the latter. |
Name change from tip/309.tip to tip/309.md.
|
| < | < | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 309: Expose the Expression Parsing Author: Arjen Markus <[email protected]> State: Draft Type: Project Vote: Pending Created: 07-Jan-2008 Post-History: Tcl-Version: 8.7 Keywords: expr, parse ----- # Abstract This TIP proposes a new command to expose the parsing of expressions by the **expr** command. This will make it much easier to implement alternative number systems, such as complex numbers, or to implement symbolic algebra. # Rationale The **expr** command uses the traditional infix notation for arithmetical expressions. Tcl itself uses a prefix notation. While it is quite easy to create a set of procedures to do complex number arithmetic, using them means the use of prefix notation, for example: A polynomial expression like _1 \+ i\*z\*\*2_ could become: [add [complex 1 0] [mult [complex 0 1] $z $z] \(where [complex] is used to make sure the constants are complex\). People used to the infix notation will find this a very clumsy, if not error-prone way of working. Basic symbolic algebra, like the determination of a derivative \(useful for certain numerical algorithms\) is much easier when working with the prefix notation: deriv [add $expr1 $expr2] --> add [deriv $expr1] [deriv $expr2] This calls for an easy way to convert an infix notation to Tcl's prefix notation. # Proposal Introduce a new command, tentatively called s-expr, as this is the traditional term used in LISP for expressions in the prefix notation, that converts a given infix expression into an equivalent prefix expression. The rules are simple: * Any valid **expr** expression can be converted. Invalid expressions result in the same error messages as if they were meant for **expr**. * The symbolic name for the command is simply the same as the string that represents the operation. * Operations have the same precedence as for **expr**. This TIP does not include a mechanism for introducing new operations. * Functions are translated into a command of the same name \(no particular namespace\) and the list of comma-separated arguments is converted into an ordinary sequence of arguments. * Errors that result from the evaluation of the expression are handled by the particular implementation of the operations and functions. * The resulting string can then be used by **eval** or **uplevel** to run the set of commands in the right order. # Implementation Notes There is no implementation of this command yet, but here is a sketch: * Let the **expr** parser construct a parse tree from the command. * Let a new function convert the parse tree into a string holding the prefix expression and pass that to the interpreter as the result of [s-expr]. This limits the sort of expressions \(in particular "constants" as understood by the specific arithmetic system\) to expressions that can be parsed by the **expr** parser, but as this now handles lists, as a consequence of the **in** and **ni** operations, this does not seem a severe limitation. The advantage of this approach is that much of the hard work is already done and that compatibility with the **expr** command is ensured. # Copyright This document is placed in the public domain |
Name change from tip/31.tip to tip/31.md.
|
| < | < | | | | | | | | | | | | | | | > | | | 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 | # TIP 31: CVS tags in the Tcl and Tk repositories Author: Don Porter <[email protected]> Author: miguel sofer <[email protected]> Author: Jeff Hobbs <[email protected]> Author: Kevin Kenny <[email protected]> Author: David Gravereaux <[email protected]> Author: Donal K. Fellows <[email protected]> Author: Andreas Kupries <[email protected]> Author: Donal K. Fellows <[email protected]> Author: <[email protected]> Author: Kevin Kenny <[email protected] > State: Draft Type: Informative Vote: Pending Created: 12-Mar-2001 Post-History: ----- # Abstract This document keeps a record of the CVS tags used in the Tcl and Tk repositories and their meanings. # Background CVS uses tags to collectively label a particular set of revisions of a particular set of files. With a tag, one may easily request all the revisions of all the files that correspond to something meaningful, such as an official release of a project. There are two kinds of tags provided by CVS. First is the release tag |
︙ | ︙ | |||
43 44 45 46 47 48 49 | A tag may be used in a CVS repository only once, so we must keep track of what tags have already been used, and what they mean. The remaining sections of this TIP record the tags in use. This TIP should be kept up to date by adding any new tags here as they are added to the CVS repository. | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 | A tag may be used in a CVS repository only once, so we must keep track of what tags have already been used, and what they mean. The remaining sections of this TIP record the tags in use. This TIP should be kept up to date by adding any new tags here as they are added to the CVS repository. # Release Tags The following tags in the Tcl and Tk CVS repositories correspond to the following releases of Tcl/Tk: * _core-8-6-b1_ - Tcl/Tk 8.6b1 * _core-8-6-a3_ - Tcl/Tk 8.6a3 * _core-8-6-a2_ - Tcl/Tk 8.6a2 * _core-8-6-a1_ - Tcl/Tk 8.6a1 * _core-8-5-6_ - Tcl/Tk 8.5.6 * _core-8-5-5_ - Tcl/Tk 8.5.5 * _core-8-5-4_ - Tcl/Tk 8.5.4 * _core-8-5-3_ - Tcl/Tk 8.5.3 * _core-8-5-2_ - Tcl/Tk 8.5.2 * _core-8-5-1_ - Tcl/Tk 8.5.1 * _core-8-5-0_ - Tcl/Tk 8.5.0 * _core-8-5-b3_ - Tcl/Tk 8.5b3 * _core-8-5-b2_ - Tcl/Tk 8.5b2 * _core-8-5-b1_ - Tcl/Tk 8.5b1 * _core-8-5-a6_ - Tcl/Tk 8.5a6 * _core-8-5-a5_ - Tcl/Tk 8.5a5 * _core-8-5-a4_ - Tcl/Tk 8.5a4 * _core-8-5-a3_ - Tcl/Tk 8.5a3 * _core-8-5-a2_ - Tcl/Tk 8.5a2 * _core-8-5-a1_ - Tcl/Tk 8.5a1 * _core-8-4-18_ - Tcl/Tk 8.4.18 * _core-8-4-17_ - Tcl/Tk 8.4.17 * _core-8-4-16_ - Tcl/Tk 8.4.16 * _core-8-4-15_ - Tcl/Tk 8.4.15 * _core-8-4-14_ - Tcl/Tk 8.4.14 * _core-8-4-13_ - Tcl/Tk 8.4.13 * _core-8-4-12_ - Tcl/Tk 8.4.12 * _core-8-4-11_ - Tcl/Tk 8.4.11 * _core-8-4-10_ - Tcl/Tk 8.4.10 * _core-8-4-9_ - Tcl/Tk 8.4.9 * _core-8-4-8_ - Tcl/Tk 8.4.8 * _core-8-4-7_ - Tcl/Tk 8.4.7 * _core-8-4-6_ - Tcl/Tk 8.4.6 * _core-8-4-5_ - Tcl/Tk 8.4.5 * _core-8-4-4_ - Tcl/Tk 8.4.4 * _core-8-4-3_ - Tcl/Tk 8.4.3 * _core-8-4-2_ - Tcl/Tk 8.4.2 * _core-8-4-1_ - Tcl/Tk 8.4.1 * _core-8-4-0_ - Tcl/Tk 8.4.0 * _core-8-4-b2_ - Tcl/Tk 8.4b2 * _core-8-4-b1_ - Tcl/Tk 8.4b1 * _core-8-4-a4_ - Tcl/Tk 8.4a4 * _core-8-4-a3_ - Tcl/Tk 8.4a3 * _core-8-4-a2_ - Tcl/Tk 8.4a2 * _core-8-4-a1_ - Tcl/Tk 8.4a1 * _core-8-3-4_ - Tcl/Tk 8.3.4 * _core-8-3-3_ - Tcl/Tk 8.3.3 * _core-8-3-2_ - Tcl/Tk 8.3.2 * _core-8-3-1_ - Tcl/Tk 8.3.1 * _core-8-3-0_ - Tcl/Tk 8.3.0 * _core-8-3-b2_ - Tcl/Tk 8.3b2 * _core-8-3-b1_ - Tcl/Tk 8.3b1 * _core-8-2-3_ - Tcl/Tk 8.2.3 * _core-8-2-2_ - Tcl/Tk 8.2.2 * _core-8-2-1_ - Tcl/Tk 8.2.1 * _core-8-2-0_ - Tcl/Tk 8.2.0 * _core-8-2-b3_ - Tcl/Tk 8.2b3 * _core-8-2-b2_ - Tcl/Tk 8.2b2 * _core-8-2-b1_ - Tcl/Tk 8.2b1 * _core-8-1-1_ - Tcl/Tk 8.1.1 * _core-8-1-0_ - Tcl/Tk 8.1.0 * _core-8-1-b3_ - Tcl/Tk 8.1b3 * _core-8-1-b2_ - Tcl/Tk 8.1b2 * _core-8-1-b1_ - Tcl/Tk 8.1b1 * _core-8-0-5_ - Tcl/Tk 8.0.5 * _core-8-0-4_ - Tcl/Tk 8.0.4 * _core-8-0-3_ - Tcl/Tk 8.0.3 * _core-8-0-2_ - Tcl/Tk 8.0p2 # Branch Tags - Official Development The following branch tags label branches of development from which releases of Tcl/Tk are generated: * _HEAD_ - current development of new features; spawns future alpha and beta releases. * _core-8-5-branch_ - bug fix branch; spawns 8.5._X_ releases after 8.5.2. * _core-8-4-branch_ - bug fix branch; spawns 8.4._X_ releases after 8.4.2. # Branch Tags - Features The following branch tags label branches on which features are being developed and tested. No releases of Tcl/Tk will be spawned from these branches. As the features mature, they will be merged onto the HEAD branch, or they may be rejected. * _core-8-4-win-speedup_ \(Tk\) - Work on improving performance of Tk on the Windows platforms. * _tip-59-implementation_ \(Tcl\) - For coordinating between Andreas Kupries and the platform maintainers on implementing [[59]](59.md). * _mod-8-3-4-branch_ \(Tcl\) - Contains the modularization work done by ActiveState for Cisco. Not for public modification. * _dgp-refactor_ \(Tcl\) - Various refactoring exercises. * _kennykb-numerics-branch_ \(Tcl\) - Explorations into improving Tcl's numeric properties, including support for large integers and rationals, and improvements to Tcl's floating point conversions. * _msofer-wcodes-branch_ \(Tcl\) - Experimental features for the bytecode engine. * _tip-257-implementation-branch_ \(Tcl\) - For development of the implementation of [[257]](257.md). Branch root version at the tag _tip-257-implementation-branch-root_. * _tip-278-branch_ \(Tcl\) - Work on [[278]](278.md). * _core-stabilizer-branch_ \(Tcl/Tk\) - Branch where the version number is bumped to the next level of stability above the HEAD for advance testing of issues that might arise when the HEAD is declared more stable. * _tip-162-branch_ \(Tcl\) - Work on [[162]](162.md). Includes extreme windows channel driver rewrite. Maintained by [email protected] # Dead Branches The following branch tags label branches that are no longer being developed. Some are old official branches from which releases are no longer being spawned. Others are feature development branches that have been merged into an official branch, or rejected. * _macosx-8-4-branch_ - Branch used during MacOSX porting work. Merged into 8.4.0. * _dkf-64bit-support-branch_ \(Tcl\) - Work on supporting 64-bit numbers, particularly on 32-bit platforms \(including large file support.\) See [[72]](72.md) for overview. Results merged into HEAD. * _kennykb-tip-22-33_ \(Tcl\) - Work on implementing the changes described in [[22]](22.md) and [[33]](33.md). Abandoned. * _dgp-privates-into-namespace_ \(Tk\) - Work on moving Tk's private commands and variables into the ::tk namespace and its children \(see [[44]](44.md).\) Merged into Tk 8.4a3. * _core-8-3-1-io-rewrite_ \(Tcl\) - Work rewriting Tcl's IO Channels to correct problems with the implementation of stacked channels. Merged into Tcl 8.3.2 and Tcl 8.4a2. * _daves-chop-branch_ \(Tcl\) - Attempts to modularize subsystems so they can be easily removed at compile-time. First step towards a 'tinytcl' on the HEAD rather than starting with an older version. \(maintained by [email protected]\) * _daves-mk-branch_ \(Tcl\) - On-going work to improve the native windows makefiles. One top-root makefile.win will serve as the starting point for MSVC\+\+, BCC, and Watcom. Extreme use of shared info will highlight this new system. This is not TEA - this is anti-TEA. \(maintained by [email protected]\) * _core-8-3-1-branch_ - Spawned Tcl/Tk 8.3.X releases. * _core-8-2-1-branch_ - Spawned Tcl/Tk 8.2.X releases. * _core-8-1-branch-old_ - Spawned Tcl/Tk 8.1bX releases. * _dev-stubs-branch_, _dev-8-1-stubs-branch_ - Two branches on which the stubs interfaces were developed. Merged into Tcl 8.1. * _msofer-bcEngine_ \(Tcl\) - Work on improving performance of the bytecode engine. # Copyright This document has been placed in the public domain. |
Name change from tip/310.tip to tip/310.md.
|
| < | < | | | | | | | | > | | | | | | | | | | | | | | | | < > | | | | | | | | < > | | | | | | | | | | | | | | | < | > | > | 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 | # TIP 310: Add a New Pseudo-Random Number Generator Author: Arjen Markus <[email protected]> State: Rejected Type: Project Vote: Done Created: 07-Jan-2008 Post-History: Tcl-Version: 8.6 Keywords: expr ----- # Abstract This TIP proposes to add a new **expr** function: a random number generator with a longer sequence than the one currently in the core. # Rationale The **expr** command has used a straightforward implementation of a pseudo-random number generator via the rand\(\) function for many years. This has a number of desirable properties, but better ones \(e.g. with a longer sequence\) have been known for a long time. This TIP proposes a new function as an alternative PRNG. PRNGs with different properties can be important for Monte Carlo simulations and other algorithms that require large amounts of random numbers without having to worry about the sequence length. # Proposal Introduce a new function, _randM\(\)_, as an alternative PRNG to the **expr** command. This function is based on work by George Marsaglia and implementations in many different languages are available on the Internet. There will be a corresponding seed function _srandM\(x\)_. The new function is not a replacement of the original rand\(\) function. # Implementation With the new tcl::mathfunc mechanism \([[232]](232.md)\) it should be simple to add this function to the core. An example implementation in Tcl is given below: # marsaglia.tcl -- # Implementation of a PRNG according to George Marsaglia # namespace eval ::PRNG { variable mod [expr {wide(256)*wide(256)*wide(256)*wide(256)-5}] variable fac [expr {wide(256)*wide(32)}] variable x1 [expr {wide($mod*rand())}] variable x2 [expr {wide($mod*rand())}] variable x3 [expr {wide($mod*rand())}] puts $mod } proc ::PRNG::marsaglia {} { variable mod variable fac variable x1 variable x2 variable x3 set xn [expr {($fac*($x3+$x2+$x1))%$mod}] set x1 $x2 set x2 $x3 set x3 $xn return [expr {$xn/double($mod)}] } # Copyright This document is placed in the public domain |
Name change from tip/311.tip to tip/311.md.
|
| < | < | | | | | | | | | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 311: Tcl/Tk 8.6 Release Calendar Author: Don Porter <[email protected]> Author: Larry W. Virden <[email protected]> Author: Joe Mistachkin <[email protected]> Author: Pat Thoyts <[email protected]> Author: Miguel Sofer <[email protected]> Author: Lars Hellström <[email protected]> Author: Alexandre Ferrieux <[email protected]> Author: Arnulf Wiedemann <[email protected]> Author: Trevor Davel <[email protected]> Author: Donal K. Fellows <[email protected]> Author: Jan Nijtmans <[email protected]> State: Draft Type: Informative Vote: Pending Created: 08-Jan-2008 Post-History: ----- # Abstract This TIP serves to coordinate Tcl/Tk 8.6 development releases and the features they deliver. # Introduction Following up on a message to the '[email protected]' mailing list, <http://aspn.activestate.com/ASPN/Mail/Message/tcl-core/3594952> , a draft release calendar for Tcl/Tk 8.6 alpha and beta releases is presented below. The intent is for developers working on Tcl and Tk to add under each release date those features they intend to make part of that release. For features which already are described by another TIP, a reference to that TIP is sufficient, and the recommended way to update this page. For features which have not yet been TIPped, a brief description and the names of those actively working on it are an acceptable temporary replacement, but should be replaced with a TIP reference as soon as one is ready. This is meant to be a working document, which gets updated by all stakeholders to reflect ongoing progress and any changes of plan. It's not a contract or a promise, just a place to record the intents of an entire community of developers. Anything in it might be revised, and any intent expressed in it might well not be fulfilled. Due to its nature, there will never be any vote on this TIP. It is more analogous to similar informational TIPs like [[31]](31.md). # Release Calendar ## Tcl/Tk 8.6a1; Release Date: June 25, 2008 * [[230]](230.md), Tcl Channel Transformation Reflection API * [[257]](257.md), Object Orientation for Tcl * [[285]](285.md), Script Cancellation with **interp cancel** and Tcl\_CancelEval * [[317]](317.md), Extend **binary** Ensemble with Binary Encodings ## Tcl/Tk 8.6a2; Release Date: August 25, 2008 * [[304]](304.md), A Standalone **chan pipe** Primitive for Advanced Child IPC * NRE core. This is an internal change that allows infinite recursion and enables new features \(like **::tcl::unsupported::tailcall**\). Official API exposure was in later versions. ## Tcl/Tk 8.6a3; Release Date: October 10, 2008 * [[195]](195.md), A Unique Prefix Handling Command * [[236]](236.md), Absolute Positioning of Canvas Items * [[265]](265.md), A Convenient C-side Command Option Parser for Tcl * [[308]](308.md), Tcl Database Connectivity \(TDBC\) * [[313]](313.md), Inexact Searching in Sorted List * [[314]](314.md), Ensembles with Parameters * [[315]](315.md), Add pathSeparator to tcl\_platform Array * [[316]](316.md), Portable Access Functions for Stat Buffers * [[318]](318.md), Extend Default Whitespace in **string trim** Beyond ASCII * [[320]](320.md), Improved Variable Handling in the Core Object System * [[323]](323.md), Do Nothing Gracefully * [[326]](326.md), Add **-stride** Option to **lsort** * [[327]](327.md), Proper Tailcalls * [[328]](328.md), Coroutines * [[330]](330.md), Eliminate interp->result from the Public Headers * [[331]](331.md), Allow **lset** to Extend Lists ## Tcl/Tk 8.6b1; Release Date: December 23, 2008 * [[97]](97.md), Moving Vertices of Canvas Items * [[119]](119.md), Angled Text on a Canvas * [[197]](197.md), Unfocussed Text Widget Cursor Control * [[210]](210.md), Add **tempfile** Subcommand to **file** * [[234]](234.md), Add Support For Zlib Compression * [[307]](307.md), Make TclTransferResult\(\) Public * [[321]](321.md), Add a **tk busy** Command * [[322]](322.md), Publish the NRE API * [[324]](324.md), A Standard Dialog For Font Selection * [[329]](329.md), **Try**/**Catch**/**Finally** syntax * [[332]](332.md), Half-Close for Bidirectional Channels * [[335]](335.md), An API for Detecting Active Interpreters * [[336]](336.md), Supported Access To interp->errorline * [[337]](337.md), Make TclBackgroundException\(\) Public * [[338]](338.md), Embedder Access to Startup Scripts of \*\_Main\(\) * [[341]](341.md), Multiple **dict filter** Patterns * [[343]](343.md), A Binary Specifier for **format**/**scan** ## Tcl/Tk 8.6b2; Release Date: August 5, 2011 * [[50]](50.md), Bundle [incr Tcl] with the Core Tcl distribution > \* Note that this is Itcl-ng \(Itcl 4.0\), and it is done by the external packages mechanism. * [[162]](162.md), IPv6 Sockets for Tcl * [[171]](171.md), Change Default <MouseWheel> Bindings Behavior * [[244]](244.md), PNG Photo Image Support for Tk * [[348]](348.md), Substituted 'errorstack' / 'traceback' * [[353]](353.md), NR-enabled Expressions for Extensions * [[354]](354.md), Minor Production-Driven TclOO Revisions * [[356]](356.md), NR-enabled Substitutions for Extensions * [[357]](357.md), Export TclLoadFile > \* Enables bundling of TDBC drivers with Tcl. * [[359]](359.md), Extended Window Manager Hint Support > \* Note that this is also being backported to 8.5 and 8.4; it is in response to a change in expectations in third-party software. * [[360]](360.md), Modernize X11 Menus * [[362]](362.md), Simple 32 and 64 bit Registry Support * [[364]](364.md), Threading Support: Configuration and Package * [[381]](381.md), Call Chain Introspection and Control ## Tcl/Tk 8.6b3; Release Date: September 18, 2012 * [[106]](106.md), Add Encoding Abilities to the [dde] Command * [[376]](376.md), Bundle sqlite3 and tdbc::sqlite3 Packages * [[378]](378.md), Fixing the Performance of [[280]](280.md) * [[380]](380.md), TclOO Slots for Flexible Declarations * [[382]](382.md), Let tk\_getSaveFile ignore file overwrites * [[388]](388.md), Extending Unicode literals past the BMP * [[395]](395.md), New 'string is entier' Command * [[396]](396.md), Symmetric Coroutines, Multiple Args, and yieldto * [[397]](397.md), Extensible Object Copying * [[398]](398.md), Quickly Exit with Non-Blocking Blocked Channels * [[403]](403.md), Web Colors for Tk * [[404]](404.md), Let Message Catalogs get the Locale from their File Name ## Tcl/Tk 8.6.0: Release Date: December 20, 2012 * [[400]](400.md), Setting the Compression Dictionary and Other 'zlib' Updates * [[405]](405.md), Add Collecting Loops, the 'lmap' and 'dict map' Commands * [[413]](413.md), Unicode Support for 'string is space' and 'string trim' * [[416]](416.md), New Options for 'load' - -global and -lazy ### Pending Features These have been voted in, but not yet implemented. * [[399]](399.md), Dynamic Locale Changing for msgcat > \* May be superseded by [[412]](412.md) due to problems found with a lack of dynamism in this TIP's API. These are currently on the schedule to make 8.6, though perhaps not 8.6.0. [[406]](406.md) and [[412]](412.md) target co-distributed packages, not Tcl itself. * [[392]](392.md), Allow Bignums to be Disabled at Runtime on a Per-Interp Basis > \* May make later versions than 8.6.0 and may be backported to 8.5. * [[406]](406.md), "C" is for Cookie * [[412]](412.md), Dynamic Locale Changing for msgcat with On-Demand File Load > \* Replacement for [[399]](399.md). # Work Roster See the Wiki page, <http://wiki.tcl.tk/20966> # Copyright This document has been placed in the public domain. |
Name change from tip/312.tip to tip/312.md.
|
| < | < | | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 312: Add More Link Types Author: Rene Zaumseil <[email protected]> Author: Larry W. Virden <[email protected]> State: Draft Type: Project Vote: Pending Created: 26-Jan-2008 Post-History: Keywords: variable,trace Tcl-Version: 8.7 ----- # Abstract This TIP proposes adding a command, **Tcl\_LinkArray**, to allow linking of C variables to Tcl lists. It also adds more types of linked variable. # Rationale The current C-API allows one to only link single variables. The proposed _Tcl\_LinkArray_ function allows the linking of C-arrays to Tcl list variables. If the given _size_ value is 1 then it works like the existing _Tcl\_LinkVar_ function. The automatic creation of needed space when no _address_ value is provided could be used for testing scenarios. The new link types also allow one to link from strings and binary arrays to fixed memory locations. The use of arrays with a given _size > 1_ allows a safe and simple C-Tcl connection. Array overwrites create errors. # Specification This document proposes the following changes to the Tcl core: ## New C API Add a new public _Tcl\_LinkArray_ function to provide links of single variable and array variables. The new function would have the same parameters as the _Tcl\_LinkVar_ function, plus an additional _int size_. If the given size is 1, then we have the same functionality as before. With _size_ > 1, the linked Tcl variable is a list variable. If the given address is NULL then the function allocates the necessary space on the C side itself. > int **Tcl\_LinkArray**\(Tcl\_Interp \*_interp_, const char \*_varName_, char \*_addr_, int _type_, int _size_\) The following link types will be supported: > TCL\_LINK\_INT, TCL\_LINK\_DOUBLE, TCL\_LINK\_BOOLEAN, TCL\_LINK\_STRING, TCL\_LINK\_WIDE\_INT, TCL\_LINK\_CHAR, TCL\_LINK\_UCHAR, TCL\_LINK\_SHORT, TCL\_LINK\_USHORT, TCL\_LINK\_UINT, TCL\_LINK\_LONG, TCL\_LINK\_ULONG, TCL\_LINK\_FLOAT, TCL\_LINK\_WIDE\_UINT, TCL\_LINK\_CHARS, TCL\_LINK\_BINARY Of these, TCL\_LINK\_CHARS and TCL\_LINK\_BINARY are new, and are as defined below: TCL\_LINK\_CHARS: The address of the C variable is used as a _char \*_. The address remains always the same \(different to TCL\_LINK\_STRING\) and contains a \\0 terminated string. The \\0 counts towards the given _size_. The Tcl variable is used as a string and can contain up to _size -1_ characters. TCL\_LINK\_BINARY: The address of the C variable is used as a _unsigned char *_. The address remains always the same. Read and write operations must always contain the full sized binary string. # Reference Implementation See <https://sourceforge.net/support/tracker.php?aid=1992824> . # Notes The original TIP proposed a _link_ command to allow these things to be done from the script level; this has been removed in the test suite support because of concerns about safety and security. # Copyright This document has been placed in the public domain. |
Name change from tip/313.tip to tip/313.md.
|
| < | < | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | < | > | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 313: Inexact Searching in Sorted List Author: Peter Spjuth <[email protected]> State: Final Type: Project Vote: Done Created: 14-Feb-2008 Post-History: Keywords: Tcl Tcl-Version: 8.6 ----- # Abstract This TIP adds a new switch to **lsearch** to do a binary search to find the insertion point in a sorted list. # Rationale Sometimes, it is necessary to find the location in a sorted list where a particular new element could be inserted. Either for actual insertion or for lookups to do interpolation or approximate search in data tables. Given that the list is already sorted, it is obviously the case that the location should be located through an O\(log N\) algorithm that takes advantage of this fact \(binary searching is the most reliable method given that measuring the "distance" between two strings is a complex and expensive operation in itself\). The usefulness of the feature is shown by a quick search. I found usages in the core, in tcllib and in tklib. Given that the infrastructure for a binary search is already in **lsearch**, this is a very cheap addition. One question for the specification is exactly what index should be returned. Below an increasing list is assumed, things are equivalent for a decreasing. 1. First where element is greater than key. 2. Last where element is less than or equal to key. 3. First where element is greater than or equal to key. 4. Last where element is less than key. Here, 1 is the use case for a stable insertion sort. In the core we can find **::tcl::clock::BSearch** which returns the index of the greatest element in $list that is less than or equal to $key, i.e. type 2. The same can be found in tklib's ::khim::BSearch. In tcllib we can find **::struct::prioqueue::\_\_linsertsorted**, which would use type 1. Personally I have had use for both 2 and 3. 1 can trivialy be calculated from 2 and vice versa. Same for 3 and 4. One key difference between 1/2 and 3/4 is that 1/2 return last among equals while 3/4 returns first among equals. This means that it is easier to lay 3/4 over 1/2 by first doing an exact search. _i.e._ by doing both a -sorted and a -bisect search you get all info needed, in log\(N\) time, to get either of 1/2/3/4. Finally, I think it makes sense for **lsearch** to return an exact match if there is one, leading to type 2 being specified in this TIP. For a decreasing list, things are equivalent. The same relationships between 1/2/3/4 applies, so it is reasonable to select the same there. I saw the word bisect used for this type of operation, but a better name is probably possible if someone have a suggestion. # Specification An option **-bisect** is added to **lsearch**. This is a modifier to **-sorted** and implies **-sorted** search mode. The list to be searched thus must be sorted and how it is sorted is specified just as for unmodified **-sorted**. For an increasing list, the **-bisect** flag makes **lsearch** return the greatest index where the element is less than or equal to the key. For a decreasing list, the **-bisect** flag makes **lsearch** return the greatest index where the element is greater than or equal to the key. If the key is before the first element, or the list is empty, -1 is returned. It is illegal to use **-bisect** with either **-all** or **-not**. Note that **-inline** and **-start** are still valid, though perhaps not very useful. # Examples A stable insertion sort: set dest {} foreach elem $src { set i [lsearch -bisect -integer $dest] set dest [linsert $dest [+ $i 1] $elem] } # Reference Implementation <http://sourceforge.net/support/tracker.php?aid=1894241> # Further Use Cases Some messages on news:comp.lang.tcl provide additional motivation for this TIP: From Kevin Kenny: <[email protected]>: > [...] When I've coded binary search like that, it's generally been as part of an interpolation or approximate search procedure. For instance, **::tcl::clock::BSearch** finds, among other things, the last change of time zone at or before a given time. The cubic spline procedure in tcllib uses BSearch to find the control point just to the left of the interpolated point. There are a great many cases where you want to look up the nearest neighbour without inserting anything if there is no exact match. From Neil Madden: <[email protected]>: > Indeed. My own recent experience was in looking up annotations to display while playing back some 3D visualisation data \(through Togl\). A list of form \{timestamp annotation ts annot ...\} was used and the annotation should be displayed for any frame from that timestamp up until the next annotation. When the user can randomly seek to any position in the data it was necessary to find the nearest preceeding annotation. I hand-coded a binary search for this. This **lsearch** enhancement would have been ideal \(well, providing I massaged the data into a form suitable for use with **-index**, which I assume this TIP is compatible with\). # Alternatives Instead of making **-bisect** a modifier to **-sorted** it could be a search mode in itself. This was the original specification in this TIP. Making it a modifier makes more sense and makes documentation simpler. ## Discussion: Alternative Names Naming the option based on something like "insert", like **-insertpos** or making this an option to **linsert**; Since the spec selects variant 2, it does not return the actual insertion position. The name **-nearest** was proposed. Since the spec does not return the nearest, it is not that good. Also proposed was "**-inexact** \(by analogy with switch -exact\)." "**-inexact** is good enough for the title of the TIP, so it should be good enough for the option name. It may be tricky writing the documentation since **-sorted** already implies **-exact**." "Names that capture the meaning better are too verbose, but maybe they'll suggest a good name ... -allowmissing -maybeabsent -absent -approximate -fuzzy -insertionpointifmissing" "The difference with the new option is that the search term need not be present in the list. That distinction is what the option name should capture." # Copyright This document has been placed in the public domain. |
Name change from tip/314.tip to tip/314.md.
|
| < | < | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | < > | | | | < < > > | | | | | < > | < > | < > | < > | < > | | | | | | | | | | | | < > | | | | | < > | < > | < > | | | | | < > | | | | > < < > | < > | < > | | | | < > | | | | | | | < > | < > | < > | < > | | | < > | | | | | | | | | | | | | | | | | | | < > | | < | > | | | < > | | | | | < > | < | > | | | | | | | | | | | | | | | | | | | > | 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 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 | # TIP 314: Ensembles with Parameters Author: Lars Hellström <[email protected]> State: Final Type: Project Vote: Done Created: 26-Feb-2008 Post-History: Tcl-Version: 8.6 ----- # Abstract This TIP proposes that **namespace ensemble** commands are generalised so that they may have arguments before the subcommand name. # Rationale The introduction of **\{\*\}** for argument expansion has made it much more convenient to use command prefixes for callbacks. One particular idiom that command prefixes provide for is "ClientData" arguments, i.e., the same command is used for several different callbacks, as exactly what it does or acts on is controlled by the extra argument\(s\). Of course, both command prefixes and the "ClientData" idiom are already the rule for callbacks from the core, but **\{\*\}** will most likely make them more common also for callbacks from Tcl code. A disadvantage of this idiom is however that it currently cannot be used if the base command of a command prefix is to be an ensemble, as the subcommand name in an ensemble must follow immediately after the base command name. Callbacks from the core which take a subcommand are rare - the only obvious example is the reflected channel callback command - but in higher level code such callbacks are fairly common. Using namespace ensembles for implementing such callbacks makes the code much more modular than using a procedure would. Hence it is desirable to remove the restriction that the subcommand name of a namespace ensemble must appear as the first argument, and instead allow there to be some number of "parameter" arguments between the base command name and the subcommand name. One application of parameter arguments is to use namespace ensembles as a white-box OO system, where the parameters hold the state of the object. More explicitly, each object instance in such a system would be a command prefix consisting of \(i\) one ensemble command that handles the method dispatch and \(ii\) the necessary number of parameter arguments, whose values make up the state of the object. Being values, such objects are necessarily immutable; it is however possible to define methods which return a mutated form of the object. For light-weight objects, this system has the advantage that instances do not have to be destroyed explicitly, but of course that also means that they cannot own any resources that require explicit destruction. Some may argue that ensemble parameters are not necessary because any client data can be embedded into the prefixes of the **-map** dictionary of the ensemble. This is however only true to the extent that multiword command prefixes themselves are unnecessary; it is similarly possible to embed extra arguments into an **interp alias**. Both of these "solutions" have the disadvantage that they create an auxiliary command which one must explicitly dispose of or leak memory, whereas all memory used by a command prefix is automatically released when the last reference to it goes away. # Specification A new ensemble option **-parameters** is introduced, which takes a list of parameter names as value and defaults to the empty list. Two C functions for setting and getting the value of this option are added to the public stubs table: > int **Tcl\_SetEnsembleParameterList**\(Tcl\_Interp \*_interp_, Tcl\_Command _token_, Tcl\_Obj \*_paramList_\) > int **Tcl\_GetEnsembleParameterList**\(Tcl\_Interp \*_interp_, Tcl\_Command _token_, Tcl\_Obj \*\*_paramListPtr_\) \(This is the same pattern as for the other ensemble options, e.g. for the **-subcommands** option's implementation.\) The general structure of a namespace ensemble command call will have the form: > _baseCmd_ \{\*\}_parameterArgs_ _subCmd_ \{\*\}_otherArgs_ where the number of arguments between the base command and the subcommand is exactly the same as the number of elements in the value of the **-parameters** option. It is an error to call the _baseCmd_ with fewer arguments than the number of parameters plus one. If _cmdPrefix_ is the command prefix to which the ensemble _baseCmd_ maps the _subCmd_, then the above call gets translated into > \{\*\}_cmdPrefix_ \{\*\}_parameterArgs_ \{\*\}_otherArgs_ # Examples An ensemble for arithmetic in integer-modulo-_n_ rings can be implemented as follows: namespace eval intmod { proc + {n args} {expr {[::tcl::mathop::+ {*}$args] % $n}} proc - {n args} {expr {[::tcl::mathop::- {*}$args] % $n}} proc * {n args} {expr {[::tcl::mathop::* {*}$args] % $n}} proc / {n a b} { set c $n set r 0 set s 1 while {$b} { set q [expr {$c / $b}] set b [expr {$c - $q*[set c $b]}] set s [expr {$r - $q*[set r $s]}] } if {$a % $c == 0} then { return [expr {$r * $a / $c % $n}] } else { return -code error "No such quotient" } } proc 0 {n} {return 0} proc 1 {n} {return 1} namespace ensemble create -parameters n -subcommands {+ - * / 0 1} # That [namespace export] takes patterns as arguments starts # feeling somewhat corny when * is a common command names. } Some example results: % intmod 7 + 4 4 1 % intmod 7 - 1 6 % intmod 7 * 3 5 1 % intmod 7 / 3 2 5 % intmod 32003 / 3 2 16003 % intmod 32768 / 3 2 No such quotient % intmod wrong # args: should be "intmod n subcommand ?argument ...?" An ensemble for matrix arithmetic over some ring can be implemented as follows: namespace eval matrix { proc + {ring A B} { if {[llength $A] != [llength $B] || [llength [lindex $A 0]] != [llength [lindex $B 0]]} then { return -code error -errorcode {ARITH DOMAIN} "Matrix shapes do not match" } set res {} foreach a_row $A b_row $B { set r_row {} foreach a $a_row b $b_row { lappend r_row [{*}$ring + $a $b] } lappend res $r_row } return $res } proc - {ring A B} { if {[llength $A] != [llength $B] || [llength [lindex $A 0]] != [llength [lindex $B 0]]} then { return -code error -errorcode {ARITH DOMAIN} "Matrix shapes do not match" } set res {} foreach a_row $A b_row $B { set r_row {} foreach a $a_row b $b_row { lappend r_row [{*}$ring - $a $b] } lappend res $r_row } return $res } proc * {ring A B} { if {[llength [lindex $A 0]] != [llength $B]} then { return -code error -errorcode {ARITH DOMAIN} "Matrix shapes do not match" } set res {} foreach a_row $A { set r_row {} foreach a $a_row b_row $B { set r [{*}$ring 0] foreach b $b_row { set r [{*}$ring + $r [{*}$ring * $a $b]] } lappend r_row $r } lappend res $r_row } return $res } # ... namespace export * namespace ensemble create -parameters ringCmdPrefix } Some more example results: % set A {{1 2} {3 4}} % matrix {intmod 7} + $A $A {2 4} {6 1} % set B {{0 2} {1 3}} % matrix {intmod 100} * $A $B {2 8} {6 16} % matrix {intmod 5} * $A $B {2 3} {1 1} % matrix {intmod 5} - $A $B {1 0} {2 1} % matrix wrong # args: should be "matrix ringCmdPrefix subcommand ?argument ...?" In the same way, one can define a **polynomial** ensemble for arithmetic with polynomials over some ring. Then one can immediately start doing calculations with e.g. matrices whose coefficients are polynomials over integers modulo 2, simply by using the command prefix matrix {polynomial {intmod 2}} Composing constructions this way is a surprisingly quick way of implementing rather complex mathematical structures! A trivial mutable object class can be implemented as follows: namespace eval mutable_ns { proc get {value} {return $value} proc set {value newvalue} {list [namespace current] $newvalue} namespace export get set namespace ensemble create -parameters value } proc mutable {initval} { list [namespace which -command mutable_ns] $initval } Some example results: % set a [mutable 0] ::mutable_ns 0 % {*}$a get 0 % {*}$a foo unknown or ambiguous subcommand "foo": must be get, or set % set b [{*}$a set 3] ; # Creates a modified copy ::mutable_ns 3 % {*}$b get 3 % {*}$a get 0 # Rejected Alternatives Most of the time, only the number of parameters is relevant; their names are merely used when throwing a "wrong \# args" error. Hence an alternative would be to have taken that number as the value of the **-parameters** option, but requesting a list of names encourages the programmer to provide more information available for introspection and should help to produce better error messages. An alternative principle for forming the mapped-to command could be that the parameters should remain in the same position in the command. This would mean that rather than mapping > _baseCmd_ \{\*\}_parameterArgs_ _subCmd_ \{\*\}_otherArgs_ to > \{\*\}_cmdPrefix_ \{\*\}_parameterArgs_ \{\*\}_otherArgs_ one would map it to > [**lindex** _cmdPrefix_ 0] \{\*\}_parameterArgs_ \{\*\}[**lrange** _cmdPrefix_ 1 end] \{\*\}_otherArgs_ but this is slightly more complicated to do, and it seems less useful. For example, this would prevent using an **apply** _lambda_ form of _cmdPrefix_ in an ensemble with parameters. # Future Extensions In analogy with the **-unknown** handler for an ensemble, it might be useful to have a handler for ensembles being called with _too few_ arguments; it is not uncommon for ensemble-like commands that one in certain cases can omit the subcommand name. Possibly this functionality could even be integrated into the **-unknown** handler. There is however nothing in that which is directly related to the issue of ensembles having parameters, other than that parameters make it possible to call an ensemble command with way too few arguments instead of just one too few. # Reference Implementation A reference implementation is available as SF Tcl patch \#1901783. <https://sourceforge.net/support/tracker.php?aid=1901783> ## Notes One detail in this implementation which might require further consideration because it results in script-level-visible behaviour is the matter of how the list of parameter names is turned into error messages. Currently that is done by \(effectively\) **join**ing the list elements, but a possible alternative is to use the string representation of the list. Joining seems to give better control to the user of what gets put in the message, but the results are probably equivalent for all alphanumeric choices of parameter names. Deep down, this touches upon the matter of how the user may distinguish actual argument values from formal argument names in syntax error messages. As far as I can tell, there currently isn't a way of doing that, but perhaps there should be. In want of clear rules for this, the reference implementation doesn't seem to fare any worse than what is already in the core. # Copyright This document has been placed in the public domain. |
Name change from tip/315.tip to tip/315.md.
|
| < | < | | | | | | | > | | | | | | | | | < > | | > | 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 | # TIP 315: Add pathSeparator to tcl_platform Array Author: Hai Vu <[email protected]> State: Final Type: Project Tcl-Version: 8.6 Vote: Done Created: 04-Apr-2008 Post-History: ----- # Abstract This TIP proposes a mechanism for determining the platform's path separator. The path separator is currently ":" in Unix and ";" in DOS/Windows. # Rationale Under Windows, the PATH environment variable consists of many paths, separated by semicolons \(";"\). Meanwhile, Unix uses colon to separate the paths \(":"\). Scripts that need to work on both platforms while parsing platform-specific PATH-like environment variables \(PATH is just the most common of these\) currently need to contain the mapping from platform-type to separator, but this is not especially flexible and some script authors are also inclined to forget about this particular difference. Thus, to aid portability, this TIP proposes adding an element to the **tcl\_platform** array, **pathSeparator**, which describes the path separator for the current platform. # Example Usage The following example prints each component of the PATH environment on a separate line: set pathList [split $env(PATH) $tcl_platform(pathSeparator)] foreach path $pathList { puts $pathList } Alternatively: puts [string map [list $tcl_platform(pathSeparator) \n] $env(PATH)] # Copyright This document has been placed in the public domain. |
Name change from tip/316.tip to tip/316.md.
|
| < | | | | | | < | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 316: Portable Access Functions for Stat Buffers State: Final Type: Project Tcl-Version: 8.6 Vote: Done Post-History: Author: Donal K. Fellows <[email protected]> Created: 02-May-2008 ----- # Abstract Tcl exposes the definition of the _struct stat_ type to users of its C API, but this can vary between builds. This TIP proposes a set of portable functions for reading \(portable\) fields out of those structures so that code does not need to match the API version when reading the fields \(the most common case by far\). # Rationale The _struct stat_ type used by Tcl can be one of many different types depending on compile-time options \(as a consequence of 64-bit filesystem support\). Tcl conceals these details by wrapping the type as a _Tcl\_StatBuf_ and providing a way to allocate these independently of compiler configuration. However, there is no way to access the contents of the field without binding to a particular type i.e. particular compile time configuration of Tcl \(and not necessarily the extension code using the API!\) This TIP proposes a set of simple access functions to conceal these details and enable the portable read-only use of the _Tcl\_StatBuf_ type. # Proposed Change This TIP proposes that the following functions will be defined. Each will take a pointer to a _Tcl\_StatBuf_ as its only argument, and will return the contents of the field indicated below. Tcl\_GetFSDeviceFromStat: Returns the _st\_dev_ field as an unsigned integer. Tcl\_GetFSInodeFromStat: Returns the _st\_ino_ field as an unsigned integer. Tcl\_GetModeFromStat: Returns the _st\_mode_ field as an unsigned integer. Tcl\_GetLinkCountFromStat: Returns the _st\_nlink_ field as an integer. Tcl\_GetUserIdFromStat: Returns the _st\_uid_ field as an integer. Tcl\_GetGroupIdFromStat: Returns the _st\_gid_ field as an integer. Tcl\_GetDeviceTypeFromStat: Returns the _st\_rdev_ field as an integer. Tcl\_GetAccessTimeFromStat: Returns the _st\_atime_ field as a wide integer. Tcl\_GetModificationTimeFromStat: Returns the _st\_mtime_ field as a wide integer. Tcl\_GetChangeTimeFromStat: Returns the _st\_ctime_ field as a wide integer. Tcl\_GetSizeFromStat: Returns the _st\_size_ field as an unsigned wide integer. Tcl\_GetBlocksFromStat: Returns the _st\_blocks_ field as an unsigned wide integer. Tcl\_GetBlockSizeFromStat: Returns the _st\_blksize_ field as an unsigned integer. Some platforms may support other fields; these are not universal and are hence not portable. # Copyright This document has been placed in the public domain. |
Name change from tip/317.tip to tip/317.md.
|
| < | < | | | | | | | | > | | | | | | | | | | | | | | | | | | > | 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 | # TIP 317: Extend binary Ensemble with Binary Encodings Author: Pat Thoyts <[email protected]> State: Final Type: Project Vote: Done Created: 03-May-2008 Post-History: Keywords: base64,uuencode,hex,transfer encoding Tcl-Version: 8.6 ----- # Abstract This TIP extends the **binary** command with implementations in C of commonly used binary encodings. In particular the _base64_ encoding is implemented but the Tcl ensemble scheme [[112]](112.md) can be used to provide simple extension of the implemented formats. # Specification The **binary** command ensemble will be extended to include two new subcommands, **encode** and **decode**. Each subcommand will accept two arguments. The first is the name of an encoding format and the second is the data to be operated upon. > **binary encode** _format ?-option value ...? data_ > **binary decode** _format ?-option value ...? data_ In keeping with the nature of the **binary** command, the _data_ argument is treated as a byte array. This means that users should ensure their data is already in a suitable character encoding before applying a binary encoding. This is already a requirement for other implementations of this functionality \(e.g. the tcllib and Trf packages\). The initial set of binary encodings consists of **base64**, **uuencode** and **hex**. The implementation of the **encode** and **decode** subcommands will make use of the Tcl ensemble command mechanism \([[112]](112.md)\) and will therefore be extensible via the ensemble mechanism. # Reference Implementation A patch against the Tcl HEAD \(8.6\) is located at <http://sf.net/tracker/?func=detail&aid=1956530&group\_id=10894&atid=310894> # Copyright This document has been placed in the public domain. |
Name change from tip/318.tip to tip/318.md.
|
| < | < | | | | | | | > | | | | | | | | | > | 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 | # TIP 318: Extend Default Whitespace in 'string trim' Beyond ASCII Author: Bill Poser <[email protected]> State: Final Type: Project Tcl-Version: 8.6 Vote: Done Created: 13-May-2008 Post-History: ----- # Abstract This TIP extends the **string trim**, **string trimleft**, and **string trimright** subcommands to function properly with non-roman writing systems by adding non-ASCII space characters to the default list of characters to be trimmed. # Rationale By default **string trim** and its single-sided variants remove ASCII whitespace characters. Some writing systems use other whitespace characters. Adding these characters to the default list will extend the Unicode-friendliness of Tcl. The characters proposed to be added are: U+1361 ETHIOPIC WORDSPACE U+1680 OGHAM SPACE MARK U+3000 IDEOGRAPHIC SPACE # Copyright This document has been placed in the public domain. |
Name change from tip/319.tip to tip/319.md.
|
| < | < | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 319: Implement Backwards Compatibility for ttk Themed Widgets in tk Widgets Author: Eric Taylor <[email protected]> State: Draft Type: Project Tcl-Version: 8.7 Vote: Pending Created: 04-Jun-2008 Post-History: ----- # Abstract This TIP calls for the implementation of backward compatibility between ttk themed widgets and conventional tk widgets. It does this by describing configuration options that specify how to deal with unsupported options \(error, ignore, or call supplied callbacks\) where full compatibility is not feasible. Configuration should be both global \(all widgets\) and specific \(by class or individual widget\). # Rationale Tk 8.5 now includes a parallel set of widgets, created through calls to similar widget constructors, but invoked using the namespace **ttk::** prepended to the name of an existing widget. For example, **ttk::button** creates a themed button, while the unqualified **button** creates standard Tk button widgets. One of the stated purposes of these new widgets is to bring Tk up to the standards now expected for attractive looking GUI programs. The **ttk** package does this quite well, but only for new programs. Imagine the leverage we would have if we could upgrade older programs \(easily and automatically\) to use these widgets. While one can use an editor and add in the **ttk::** to each widget creation call \(which then begs the question of why we can't have this done automatically with a simple configuration procedure\) one is often stuck when trying to implement the same behavior since many Tk options which are currently unsupported in ttk. In addition, there are packages, such as visual tcl, which write conventional tk code. These programs cannot easily be converted to use the new widgets, but still need to be maintained using the vtcl program. This TIP proposes that all current Tk widget options be supported where feasible and that the following command be fully implemented to permit older Tk-oriented programs run unaltered using the themed set of widgets. namespace import -force ttk::* Since the ttk widgets don't have all the same options, there would need to be some compatibility code that could simulate the old behavior. For example, in **button**, there is no longer a **-background** color option, nor is there **-padx** and **-pady**. Sometimes these missing options can be implemented, for example, using **-padding** would let one implement partial behavior. While it would be preferable to implement these options directly, an alternative would be to select a compatability handling mode of ignore, error, or callback to aid the developer in implementing missing options. # Proposal To that purpose, I propose some kind of configuration option, for example: > **ttk::compatibility** ?**-onerror** [**ignore**\|**error**\|**callback**]? ?**-callback** _proc_? ?**-class** [_widget-class_\|**all**]? When the callback procedure is invoked, it should be passed additional parameters which would completely identify, 1. The widget \(e.g. **.frame.button**\) 2. The option that is not directly supported \(e.g. **-pady**\) 3. The value specified for that option \(the argument following the _-option_\) 4. Anything else I've forgotten The above should also be configured globally \(all widgets\) or on a widget by widget basis. For individual widgets, there should be a configuration option for the above. I would think that most of this should be implementable with pure tcl/tk proc's. # Copyright This document has been placed in the public domain. |
Name change from tip/32.tip to tip/32.md.
|
| < | < | | | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 32: Add Tcl_Obj-enabled counterpart to Tcl_CreateTrace Author: David Cuthbert <[email protected]> Author: Kevin Kenny <[email protected]> State: Final Type: Project Vote: Done Created: 23-Mar-2001 Post-History: Discussions-To: news:comp.lang.tcl Keywords: trace,Tcl_Obj Tcl-Version: 8.4a4 ----- # Abstract This document proposes to add Tcl\_Obj support for trace procedures written in C. # Rationale The _Tcl\_Obj_ system was introduced in version 8.0, making computations \(potentially\) much more efficient by eliminating many type conversions to and from strings. However, the trace API continues to require character strings in both command and variable traces. In addition, the _Tcl\_CreateTrace_ function interacts rather badly with the bytecode compiler, since it forbids inlining of functions. Since many trace applications ignore the built-in functions that would have been inlined, this restriction is not needed by many applications. This TIP proposes to make it optional in the revised API. The trace mechanism in the Tcl library has been underused for some time, partly because it is awkward. While the profiler, tracer and debugger from TclX and the debugger from Expect have seen some limited success, they are certainly not familiar to the majority of Tcl users. The second author of this TIP has experimented with using the trace mechanism to build a profiler for Tcl that does not depend on source code instrumentation. His experience was that: * It is very difficult to write useful trace procedures without resorting to _tclInt.h_ -- in particular, the fact that only the command name and not the _Tcl\_Command_ token is passed meant that _Tcl\_FindCommand_ is needed to do virtually anything useful. * The profiler often perturbs the run-time behavior of the program, often violently. The reason is twofold. First, the string representation of all of a traced command's arguments must be constructed, even though the trace procedure has no need for them. Second, the presence of the trace procedure defeats the bytecode compiler. Since the user of a profiler is unlikely to care about each individual built-in command \(the common usage is to profile the time spent in procedures\), turning off inline compilation of commands is neither needed nor wanted. * The profiler traces returns from commands by subsituting the command procedure with one that is internal to the profiler itself, and restoring the command procedure upon exit. Doing so requires many needless lookups of the command name, because only the name is presented to the trace procedure, and the name is the only way to access _Tcl\_GetCommandInfo_ and _Tcl\_SetCommandInfo_. This overhead can be avoided only by including _tclInt.h_ and casting the _Tcl\_Command_ object to a _Command_ object -- in other words, by accessing the interpreter's internal data structures from the extension. This TIP is an effort to rationalize the trace interface to avoid these difficulties. # Specification The following functions shall be added to the Tcl core: 1. Tcl\_CreateObjTrace Tcl_Trace Tcl_CreateObjTrace ( Tcl_Interp* interp, int level, int flags, Tcl_CmdObjTraceProc* objProc, ClientData clientData ); > The _Tcl\_CreateObjTrace_ function adds a trace to the Tcl evaluator. The _interp_ argument is the Tcl interpreter for which tracing is being requested. The _level_ argument is the maximum depth of recursive calls; when the execution depth of the interpreter exceeds this number, the trace callback does not execute. The _objProc_ argument is the callback procedure to execute each time a Tcl command is evaluated; it is expected to have arguments and result type that match _Tcl\_CmdObjTraceProc_ below. The _clientData_ argument is client data to pass to the _objProc_ callback. Finally, the _flags_ argument gives flags that control the tracing. Initially, the only flag supported will be _TCL\_ALLOW\_INLINE\_COMPILE_. If this flag is set, the bytecode compiler is permitted to compile in-line code for the Tcl built-in commands; any command that has been compiled in-line will not be traced. > The _Tcl\_CreateObjTrace_ function returns a _trace token_ -- an object of opaque type that may be passed to _Tcl\_DeleteTrace_ to delete the trace. > The _Tcl\_CmdObjTraceProc_ will have the following type signature. typedef int Tcl_CmdObjTraceProc( ClientData clientData, Tcl_Interp* interp, int level, CONST char* command, Tcl_Command commandInfo, int objc, Tcl_Obj *CONST objv[] ); > The _clientData_ parameter is the client data that was passed to _Tcl\_CreateObjTrace_. The _interp_ parameter designates a Tcl interpreter. The _level_ parameter specifies the execution level. The _command_ parameter gives the raw UTF-8 text of the command being evaluated, before any substitutions have been performed. The _commandInfo_ parameter is an opaque _Tcl\_Command_ object that gives information about the command. The _objc_ and _objv_ parameters are the command name and parameter vector after substitution. > The trace procedure is expected to return a standard Tcl status return. If it returns _TCL\_OK_, the command is evaluated normally. If it returns _TCL\_ERROR_, evaluation of the command does not take place. The interpreter result is expected to contain an error message. If it returns any other status, such as _TCL\_BREAK_, _TCL\_CONTINUE_ or _TCL\_RETURN_, it is treated as if the command had done so. 1. Tcl\_GetCommandInfoFromToken and Tcl\_SetCommandInfoFromToken int Tcl_GetCommandInfoFromToken( Tcl_Command token, Tcl_CmdInfo* infoPtr ); int Tcl_SetCommandInfoFromToken( Tcl_Command token, CONST Tcl_CmdInfo* infoPtr ); > The _Tcl\_GetCommandInfoFromToken_ and _Tcl\_SetCommandInfoFromToken_ functions are precisely parallel to today's _Tcl\_GetCommandInfo_ and _Tcl\_SetCommandInfo_ procedures, except that they accept an opaque _Tcl\_Command_ object instead of a command name. They are provided so that trace procedures \(and other extensions that have such an object\) can adjust command information without having to go through two extra lookups in the command hash by applying _Tcl\_GetCommandInfo_ to the result of _Tcl\_GetCommandName._ # Change History 10 February 2002 - Moved to Final Status with slight revisions in the names and arguments of Tcl\_GetCommandInfoFromToken and Tcl\_SetCommandInfoFromToken. 3 November 2001 - Reworked the entire TIP. Changed the object trace handling to work with _Tcl\_Command_ objects instead of command names. Removed the object-based variable trace procedures. Since Tcl variable names really are character strings and not Tcl objects, object-based variable trace procedures would be _slower_ than the string-based ones. 30 March 2001 - Changed return value of objProc to a Tcl\_Obj \* instead of int \(and using the interpreter result to indicate an error\). This is more consistent with the current behavior \(but without the bug\). -dac # Copyright Copyright © 2000 by David Cuthbert. Distribution in whole or part, with or without annotations, is unlimited. Copyright © 2001 by Kevin B. Kenny. Distribution in whole or part, with or without annotations, is unlimited. |
Name change from tip/320.tip to tip/320.md.
|
| < | < | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 320: Improved Variable Handling in the Core Object System Author: Donal K. Fellows <[email protected]> State: Final Type: Project Vote: Done Created: 13-Jun-2008 Post-History: Keywords: TclOO Tcl-Version: 8.6 ----- # Abstract This TIP specifies new configuration commands that allow variables to be used in methods of the core object system without explicit declaration in each method. # Rationale During the discussions leading up to the vote on [[257]](257.md), it became apparent that being able to access at least some variables of an object without explicit declaration in each method was desirable. Doing this would make working with the core object system much easier in many common cases, and would also allow for potentially more efficient implementation. However, there is a balance to be drawn. If every variable of the object was made available in the method by default \(the simplest case\) there would frequently be problems with interactions between the formal arguments of a superclass's methods and the instance variables of a subclass! That would be highly undesirable, as it completely breaks the principle of isolation of class implementations. There are two ways of dealing with this issue. 1. Make the variables understood by a particular class be distinct from those understood by subclasses of the class. 2. Only bring those variables into scope that are actually declared by a particular class. Studying the first alternative, there are two ways to actually achieve this: not putting the variables in a namespace but actually using a separate structure \(poor, because then we would lose the ability to easily use the variable with many of Tcl's general variable facilities\), or modifying the namespace-visible name of each variable to include some unique string coupled to the class declaring it. Though I think that the second option is better than the first \(actual implementations would be able to use the **oo::object** class's **variable** and **varname** methods to hide many of the details where they are currently exposed at all\) I still do not particularly like it since it would mean that the cases where a class and a subclass _want_ to refer to the same variable are very awkward. Hence I think that there should be a mechanism for declaring what variables a class has, that those names should be the namespace-visible names of the variables, and that only those variables that are declared by a particular class should be _automatically_ visible in the class's methods \(including the constructor and destructor, of course\). As a matter of basic symmetry, object-level declarations of variables and methods should also be possible. # Proposed Change Every object and every class will have associated with it a list of variable names. This list will be configurable via a subcommand of **oo::define** and introspectable. Methods \(strictly, only procedure-like methods, constructors and destructors\) will then make those variables that were declared at the same declaration level \(i.e. in the same class, or in the object itself for methods defined on the object\) available in the method body without further declaration or qualification. At declaration time, the type of the variable \(i.e. whether it is an array or a simple variable\) will not be defined; that may be done in the constructor. As there is no \(public\) C API for declaring a procedure-like method, there will not be a public C API for declaring the variables either. Note that the order in which the declaration of some methods and some variables for a class or object will not matter. ## Declaration The **oo::define** and **oo::objdefine** \(and also the **self** subcommand of **oo::define**\) will gain a new subcommand: **variable**. This will take zero or more arguments, and those arguments will form the list of variables that are made available by default. Each argument will need to be a valid variable local name without parentheses. Syntax \(other uses analogous according to normal behaviour of the class and object definition commands\): > **oo::define** _class_ **variable** ?_varName ..._? ## Introspection The list of variables declared by a particular class, _class_, may be retrieved by: > **info class variables** _class_ The list of variables declared by a particular object, _object_, may be retrieved by: > **info object variables** _object_ Note that the full list of _all_ variables \(matching an optional pattern\) in an object's namespace will be retrievable using **info object vars**; this mechanism is disjoint \(though **info object variables** will return variables that can be returned by **info object vars**\). # Implementation <https://sourceforge.net/support/tracker.php?aid=2005460> # Copyright This document has been placed in the public domain. |
Name change from tip/321.tip to tip/321.md.
|
| < | < | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 321: Add a [tk busy] Command Author: Jos Decoster <[email protected]> State: Final Type: Project Vote: Done Created: 26-Jun-2008 Post-History: Keywords: Tk,BLT,busy Tcl-Version: 8.6 ----- # Abstract The **blt::busy** commands can be used to make Tk widget busy, with all user interaction blocked and the cursor can be changed to e.g. a clock. This TIP proposes to add this useful feature to Tk. # Rationale BLT has a lot of very useful commands: **bgexec**, **busy**, **vector**, **graph** widget, **barchart** widget, ... But getting BLT to work with the latest releases of Tcl and Tk becomes more and more difficult. Some of the problems I experienced are: * internal Tk structures are mirrored * interaction with xft fails, so Tk has to be build without xft support * the build process is different from the one used in Tcl and Tk Discussions on CLT and \#tcl indicated that extracting functionality from BLT and add it to Tcl and Tk might be a good way to make the blt commands available for every Tcl programmer. This TIP proposes a way to add the blt::busy command to Tk, based on the code as found in BLT2.4z and the code as found in busy.kit. While adding the code to Tk, it was rewritten to use the Tcl\_Obj interface and the new option interface. The interface has also been simplified. The **blt::release** command was not withheld. Because often the same window is made busy again and again, using **release** in stead of **forget** might be faster. But when making an application busy, it's because it'll have to wait for another operation and/or process to finish which will typically take a much longer time than the time needed to \(re\)create the transparent window. The **names** and **isbusy** commands were replaced by the new **current** command. The confusing difference between a window which is busy, a window which was busy but still has the associated transparent window allocated and a window which was busy but no longer has its associated transparent window allocated was removed. The name of this new Tk command as currently implemented is **tk busy**, part of the **tk** command ensemble. Adding it as an option to the **grab** command might cause confusion as the **tk busy** command has the opposite functionality of the **grab** command. It blocks all user interaction rather than redirecting it to one widget. # Specification The **tk busy** command is an ensemble with a special feature that any unrecognized subcommand that starts with a period is treated as an invokation of the **hold** subcommand upon the widget with that name. ## Hold Subcommand > **tk busy** _window_ ?_option value_? > **tk busy hold** _window_ ?_option value_? Makes the window \(and its descendants in the Tk window hierarchy\) appear busy by ignoring all events sent to the window and its descendants. _Window_ must be a valid path name of a Tk widget. A transparent window is put in front of the specified window. This transparent window is mapped the next time idle tasks are processed, and the specified window and its descendants will be blocked from user interactions. Normally update should be called immediately afterward to insure that the hold operation is in effect before the application starts its processing. The following configuration options are valid: > **-cursor** _cursorName_ Specifies the cursor to be displayed when the widget is made busy. CursorName can be in any form accepted by Tk\_GetCursor. The default cursor is watch. ## Forget Subcommand > **tk busy forget** _window_ Releases resources allocated by the **tk busy** command for _window_, including the transparent window. User events will again be received by the specified window. Resources are also released when the specified window is destroyed. _Window_ must be the name of a widget previously specified in a **hold** operation, otherwise an error is reported. ## Current Subcommand > **tk busy current** ?_pattern_? Returns the pathnames of all windows that are currently made busy. If a _pattern_ is given, only the path names of busy windows matching _pattern_ are returned. ## Status Subcommand > **tk busy status** _window_ Returns the busy status of a _window_. If _window_ presently can not receive user interactions, 1 is returned, otherwise 0. ## Configure Subcommand > **tk busy configure** _window_ ?_option_? ?_value ..._? Queries or modifies the **tk busy** command configuration options for _window_. _Window_ must be the path name of a widget previously made busy by the **hold** operation. If no options are specified, a list describing all of the available options for window \(see **Tk\_ConfigureInfo** for information on the format of this list\) is returned. If _option_ is specified with no _value_, then the command returns a list describing the one named option \(this list will be identical to the corresponding sublist of the value returned if no option is specified\). If one or more _option-value_ pairs are specified, then the command modifies the given widget option\(s\) to have the given value\(s\); in this case the command returns the empty string. Options may have any of the values accepted by the hold operation. Please note that the option database is referenced through window. For example, if the widget .frame is to be made busy, the busy cursor can be specified for it by either option command: option add *frame.busyCursor gumby option add *Frame.BusyCursor gumby ## Cget Subcommand > **tk busy cget** _window option_ Queries the **tk busy** command configuration options for _window_. _Window_ must be the path name of a widget previously made busy by the **hold** operation. The command returns the present value of the specified _option_. _Option_ may have any of the values accepted by the **hold** operation. # Reference Implementation See SourceForge patch \#1997907 <https://sourceforge.net/support/tracker.php?aid=1997907> . There is no support for Mac \+ Aqua in this patch. It compiles on Mac \+ Aqua and the command will not return errors but will not resort in a _busy_ effect. Mac \+ X11 does work. # Compatibility Because the command as proposed above has the same interface and behavior as the **blt::busy** command, replacing **blt::busy** with **tk busy** is all that's needed to switch to the Tk version of the busy command. The **tk busy** command is not one-by-one compatible with the **blt::busy** command, but typical use \(**hold** and **forget**\) will not suffer a lot. Aliases or an ensemble could be used to make transition easier. # Alternatives The busy command is available as starkit from <http://tcl.tk/starkits/busy.kit> An alternative would have been to keep the interface from BLT. This would have made transition easier, but would have kept the confusing difference between _forgotten_ and _released_ busy windows. # Copyright This document has been placed in the public domain. |
Name change from tip/322.tip to tip/322.md.
|
| < | < | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 322: Publish the NRE API Author: Miguel Sofer <[email protected]> State: Final Type: Project Vote: Done Created: 13-Jul-2008 Post-History: Tcl-Version: 8.6 ----- # Abstract This TIP exposes an API to allow extension writers to take advantage of Tcl's Non-Recursive evaluation Engine. # Rationale NRE \(for **N**on-**R**ecursive **E**ngine\) is a trampoline implementation for command evaluation and bytecode execution that massively reduce Tcl's footprint on the C stack. It is conceptually related to stackless Python. NRE is fully backwards compatible with script and C extensions and has already been committed to HEAD. Extensions that use the normal Tcl API run properly but cannot take advantage of the non-recursivity. This TIP proposes to publish a small API for extension writers that will allow them to exploit the new possibilities. # Functions to be Exported The first two functions permit the creation of NRE-enabled commands. **Tcl\_NRCreateCommand** creates a command that implements an NRE interface _nreProc_. As every command needs also a regular _objProc_, the function **Tcl\_NRCallObjProc** is provided as a utility permitting a relatively simple way to generate the _objProc_ from the _nreProc_. * Tcl\_Command **Tcl\_NRCreateCommand**\(Tcl\_Interp \*_interp_, const char *_cmdName_, Tcl\_ObjCmdProc \*_proc_, Tcl\_ObjCmdProc \*_nreProc_, ClientData _clientData_, Tcl\_CmdDeleteProc \*_deleteProc_\) * int **Tcl\_NRCallObjProc**\(Tcl\_Interp \*_interp_, Tcl\_ObjCmdProc *_objProc_, ClientData _clientData_, int _objc_, Tcl\_Obj \*const *_objv_[]\) The next three functions provide the API to request an evaluation by the trampoline, after the caller returned: * int **Tcl\_NREvalObj**\(Tcl\_Interp \*_interp_, Tcl\_Obj \*_objPtr_, int _flags_\) * int **Tcl\_NREvalObjv**\(Tcl\_Interp \*_interp_, int _objc_, Tcl\_Obj *const _objv_[], int _flags_\) * int **Tcl\_NRCmdSwap**\(Tcl\_Interp \*_interp_, Tcl\_Command _cmd_, int _objc_, Tcl\_Obj \*const _objv_[]\) Finally, there is a function to register a callback that the trampoline has to execute right after a requested evaluation, typically used for cleanup. * void **Tcl\_NRAddCallback**\(Tcl\_Interp \*_interp_, Tcl\_NRPostProc *_postProcPtr_, ClientData _data0_, ClientData _data1_, ClientData _data2_, ClientData _data3_\) # Documentation NRE's internal functioning is somewhat documented at <http://msofer.com:8080/wiki?name=NRE> An example of how the API is to be used can be found at <http://msofer.com:8080/wiki?name=Exploiting\+NRE> The new API will be documented in a manual page _doc/NRE.3_. # Reference Implementation The API is already available in HEAD \(to become Tcl8.6a2\); a high level description is available at <http://msofer.com:8080/wiki?name=NRE\+short\+explanation> # Copyright This document has been placed in the public domain. |
Name change from tip/323.tip to tip/323.md.
|
| < | < | | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 323: Do Nothing Gracefully Author: Colin McCormack <[email protected]> Author: Don Porter <[email protected]> Author: Kevin B. Kenny <[email protected]> State: Final Type: Project Vote: Done Created: 06-Aug-2008 Post-History: Tcl-Version: 8.6 ----- # Abstract A number of Tcl's built-in commands currently raise errors when given arguments that would cause them to do nothing. This proposal asks that they instead simply do nothing gracefully. # Rationale With the introduction of \{\*\} syntax in Tcl 8.5 and its ability to convert one original word into zero words when an empty list is expanded, scripts using the syntax are forced to check for the empty list when passing expanded arguments to a command taking variable numbers of arguments, but arbitrarily rejecting zero arguments. For example, variable {*}$dict will currently fail if $dict has no entries. Letting no-ops simply be no-ops rather than errors greatly lightens the programming burden on callers. There may be some marginal performance benefits as well. Furthermore, there is no sound reason to constrain the argument count of these commands to be positive when an argument count of zero has a natural interpretation as a no-op. There is an elegance in permitting a function to range coherently over the complete domain. # Proposal The syntax of the following commands shall be revised as described: 1. **file delete** - accept zero pathnames. 1. **file mkdir** - accept zero directories. 1. **global** - accept zero variable names. 1. **glob** - accept zero patterns, returning list of zero matching files \(with **-nocomplain**\) or "no matches" error. 1. **lassign** - accept zero variable names. <https://sourceforge.net/support/tracker.php?aid=1671880> 1. **linsert** - accept zero elements. <https://sourceforge.net/support/tracker.php?aid=1672056> 1. **lrepeat** - accept both _number_ = 0 and zero elements. <https://sourceforge.net/support/tracker.php?aid=1671951> 1. **my variable** - accept zero variable names. 1. **namespace upvar** - accept zero variable names. 1. **tcl::tm::path add** - accept zero paths. 1. **tcl::tm::path remove** - accept zero paths. 1. **variable** - accept zero variable names. <https://sourceforge.net/support/tracker.php?aid=1881284> # Compatibilty The proposed changes convert errors into no-ops. There should be no compatibility concerns with those. # Implementation When an implementation patch is completed, it will be logged in the SF Tracker and noted here. # Exclusions Some other candidates for this treatment are intentionally left out of this proposal where for various reasons their conversion is complicated in some way, or the benefits of conversion are not as clear cut. These other commands might still be revised in a similar way, but are left for other TIPs to accomplish it so that this TIP can focus only on the low-hanging fruit. 1. **after idle** 1. **dict exists** 1. **dict set d** _val_ \(no _key_ argument\) 1. **dict unset d** _val_ \(no _key_ argument\) 1. **dict update d** _script_ \(no _key varName_ arguments\) 1. **eval** 1. **expr** 1. **file join** 1. **interp eval** 1. **namespace eval** 1. **parray** <https://sourceforge.net/support/tracker.php?aid=1739221> This feature request is more about tolerating errors than about expanding acceptance over a complete input domain. Not in the spirit of this TIP. 1. **uplevel** 1. **upvar** - presence of the optional _level_ argument makes this one messy. # Epilogue Proposed changes to **string first**, **string last**, and **string replace** in earlier revisions of the TIP that were approved by the vote have been rescinded after testing during the implementation phase revealed greater than expected issues with the incompatibilities those changes introduced. # Copyright This document has been placed in the public domain. |
Name change from tip/324.tip to tip/324.md.
|
| < | < | | | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | < > | | | < > | | | < > | | | < > | | < > | | < > | | | | | | | | > | 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 | # TIP 324: A Standard Dialog For Font Selection Author: Adrian Robert <[email protected]> Author: Daniel A. Steffen <[email protected]> State: Final Type: Project Vote: Done Created: 08-Aug-2008 Post-History: Keywords: Tk Obsoletes: 213 Tcl-Version: 8.6 ----- # Abstract This TIP proposes the addition of a font selection dialog to the set of common dialogs already available in Tk. Where possible, this dialog will be implemented using the host platform's standard dialogs. # Rationale A number of platforms \(including Windows and Mac OS X\) have standard dialogs for common user-oriented tasks, for which Tk provides an interface via commands such as **tk\_getOpenFile** and **tk\_chooseColor**. Another dialog that these platforms provide and which some Tk programs would find useful is a _standard font selector_. This TIP proposes adding a command to Tk to allow access to the platform font selection dialog where available, or to a dialog implemented in Tcl otherwise. Unlike the existing dialog commands, the new font dialog command will not return a result, as on some platforms \(Mac OS X\) the standard font dialog is modeless while on others \(Windows\) it is modal. To accommodate this difference, all user interaction with the dialog will be communicated to the caller via callbacks or virtual events. To emphasize this difference in operation between the new command and the existing Tk dialog commands the proposed name is **tk fontchooser** instead of e.g. **tk\_chooseFont**. # Proposal Tk shall have a new command ensemble **tk fontchooser** with the following syntax: > **tk fontchooser configure** ?_-option value -option value ..._? set or query one or more of the configurations options below \(analogous to Tk widget configuration\). > **tk fontchooser show** show the font selection dialog. Depending on the platform, may return immediately or only once the dialog has been withdrawn. > **tk fontchooser hide** hide the font selection dialog if it is visible and cause any pending **tk fontchooser show** command to return. ## Configuration Options -parent: specifies/returns the parent window of the font selection dialog \(similar to the _-parent_ option to other dialogs\). -title: specifies/returns the title of the dialog. Has no effect on platforms where the font selection dialog does not support titles. -font: specifies/returns the font that is currently selected in the dialog if it is visible, or that will be initially selected when the dialog is shown \(if supported by the platform\). Can be set to the empty string to indicate that no font should be selected. Fonts can be specified in any form given by the "FONT DESCRIPTION" section in font\(n\). -command: specifies/returns the command prefix to be called when a font selection has been made by the user. The command prefix is evaluated at the global level after having the specification of the selected font appended. On platforms where the font selection dialog offers the user control of further font attributes \(such as color\), additional key/value pairs may be appended before evaluation. Can be set to the empty string to indicate that no callback should be invoked. Fonts are specified by a list of form [[3]](3.md) of the "FONT DESCRIPTION" section in font\(n\) \(i.e. a list of the form _\{family size style ?style ...?\}_\). -visible: read-only option that returns a boolean indicating whether the font selection dialog is currently visible. Attempting to set this option results in an error. ## Events <<TkFontchooserVisibility>> > virtual event sent to the dialog parent whenever the visibility of the font selection dialog changes, both as a result of user action \(e.g. disposing of the dialog via OK/Cancel button or close box\) and of the **tk fontchooser show/hide** commands being called. Binding scripts can determine the current visibility of the dialog by querying the _-visible_ configuration option. <<TkFontchooserFontChanged>> > virtual event sent to the dialog parent whenever the font selection dialog is visible and the selected font changes, both as a result of user action and of the _-font_ configuration option being set. Binding scripts can determine the currently selected font by querying the _-font_ configuration option. # Notes Whenever a platform provides a suitable font dialog in its API, Tk shall not use a script-based alternative, even if this means missing out on features like the title or dynamic updating of the font during the selection process. This will help to ensure Tk applications meet platform-specific user-interface design guidelines. Callers should not expect a result from **tk fontchooser show** and may not assume that the dialog has been withdrawn or closed when the command returns. All user interaction with the dialog is communicated to the caller via the _-command_ callback and the _<<TkFontchooser\*>>_ virtual events. It is implementation dependent which exact user actions result in the callback being called resp. the virtual events being sent. Where an Apply or OK button is present in the dialog, it is expected for that button to trigger the _-command_ callback and _<<TkFontchooserFontChanged>>_ virtual event. However, on some implementations other user actions may also have that effect; on Mac OS X for instance, the standard font selection dialog immediately reflects all user choices to the caller. In the presence of multiple widgets intended to be influenced by the font selection dialog, care needs to be taken to correctly handle focus changes: the font selected in the dialog should always match the current font of the widget with the focus, and the _-command_ callback should only act on the widget with the focus. The recommended practice is to set font dialog _-font_ and _-command_ configuration options in per-widget _<FocusIn>_ handlers \(and if necessary to unset them - i.e. set to the empty string - in corresponding _<FocusOut>_ handlers\). This is particularly important for implementors of library code using the font selection dialog, to avoid conflicting with application code that may also want to use the dialog. Because the font selection dialog is application-global, in the presence of multiple interpreters calling **tk fontchooser**, only the _-command_ callback set by the interpreter that most recently called **tk fontchooser configure** or **tk fontchooser show** will be invoked in response to user action and only the _-parent_ set by that interpreter will receive _<<TkFontchooser\*>>_ virtual events. The font dialog implementation may only store \(and return\) **font actual** data as the value of the _-font_ configuration option. This can be an issue when _-font_ is set to a named font, if that font is subsequently changed, the font dialog _-font_ option needs to be set again to ensure its selected font matches the new value of the named font. # Example The following example demonstrates the recommended practice of updating the font dialog configuration with the focus: proc tip324demo {} { wm title . "TIP324 Demo" tk fontchooser configure -parent . button .b -command fcToggle -takefocus 0; fcVisibility .b bind . <<TkFontchooserVisibility>> [list fcVisibility .b] foreach w {.t1 .t2} { text $w -width 20 -height 4 -borderwidth 1 -relief solid bind $w <FocusIn> [list fcFocus $w] $w insert end "Text Widget $w" } .t1 configure -font {Courier 14} .t2 configure -font {Times 16} pack .b .t1 .t2; focus .t1 } proc fcToggle {} { tk fontchooser [expr {[tk fontchooser configure -visible] ? "hide" : "show"}] } proc fcVisibility {w} { $w configure -text [expr {[tk fontchooser configure -visible] ? "Hide Font Dialog" : "Show Font Dialog"}] } proc fcFocus {w} { tk fontchooser configure -font [$w cget -font] -command [list fcFont $w] } proc fcFont {w font args} { $w configure -font [font actual $font] } tip324demo # Alternatives [[213]](213.md) was an earlier proposal for a font selection dialog API, it was withdrawn when it became clear that it was incompatible with platforms where the standard font dialog is modeless. Alternative names for the new command have been proposed: **tk::choosefont**, **tk::chooseFont**, **tk::fontChooser**, **tk\_chooseFont**. # Reference Implementation Tk Patch 1477426 <http://sourceforge.net/support/tracker.php?aid=1477426> # Copyright This document has been placed in the public domain. |
Name change from tip/325.tip to tip/325.md.
|
| < | < | | | | | | | | > | | | | | | > | 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 | # TIP 325: System Tray Access Author: David N. Welton <[email protected]> State: Draft Type: Project Tcl-Version: 8.7 Vote: Pending Created: 25-Aug-2008 Post-History: Keywords: Tk, desktop integration ----- # Abstract Modern operating systems have a "system tray", where programs may place an icon to indicate program status. This TIP proposes that Tk should adopt some existing code in order to permit cross platform access to this functionality. # Existing code * Windows: winico * Linux: tktray * Mac: ??? Existing code is sufficient, and utilizes an acceptable license in order to repurpose it for a systray command. # Interface To be determined by the TCT, but along the lines of what tktray provides: > **tktray::icon** _pathName_ ?_options_? Create a new icon for the system tray. The application managing the system tray is notified about the new icon. It normally results in the icon being added to the tray. If there is no system tray at the icon creation time, the icon will be invisible. When a new system tray appears, the icon will be added to it. Options: -class: WM\_CLASS attribute for the icon window. Tray manager may use class name to remember icon position or other attributes. -image: image to show in the system tray. The value must be the name of a photo image. Transparency data of the photo are used to set the window's shape. The icon will be automatically redrawn or resized appropriately on any image modifications. -visible: boolean value indicating whether the icon must be visible. The system tray manager continues to manage the icon whether it is visible or not. Thus when invisible icon becomes visible, its position on the system tray is likely to remain the same. # Copyright This document has been placed in the public domain. |
Name change from tip/326.tip to tip/326.md.
|
| < | < | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 326: Add -stride Option to lsort Author: Kieran Elby <[email protected]> State: Final Type: Project Tcl-Version: 8.6 Vote: Done Created: 01-Sep-2008 Keywords: Tcl, lsort, sorting Post-History: ----- # Abstract This TIP adds a new option, **-stride**, to **lsort** to request that a list be treated as consisting of repeated groups of elements \(as opposed to sublists\), and that the the groups be sorted according to a chosen element within each group. # Rationale Flat name-value pair lists are common in Tcl - consider the output of **array get** and **dict create** or the input to **foreach**. It is surprising then that there is no command to directly sort such a list by either the name or the value elements, while preserving the name-value mapping. Doing so currently requires turning a name-value pair list into a list of sublists, using the **lsort** _-index_ option to sort them, then flattening the list again, which is rather fiddly and inefficient. While sorting name-value pair lists is no doubt the most common use case, lists containing groups of more than two elements are also reasonably common, and so providing support for groups of any size seems useful and no harder to implement. The option format follows the Feature Request here: <https://sourceforge.net/support/tracker.php?aid=747083> # Proposed Change A new option, **-stride**, taking one parameter, _grpSize_ will be added to the **lsort** command. If **-stride** is supplied, the list will be treated as consisting of groups of _grpSize_ elements, and the groups will be sorted by either their first element or, if the **-index** option is used, by the element within each group given by the first index passed to **-index** \(which is then ignored by **-index**\). Elements always remain in the same position within their group. The list length must be a multiple of _grpSize_, which in turn must be at least 2. # Examples lsort -stride 2 {carrot 10 apple 50 banana 25} returns "apple 50 banana 25 carrot 10" lsort -stride 2 -index 1 -integer {carrot 10 apple 50 banana 25} returns "carrot 10 banana 25 apple 50" lsort -stride 3 -index {0 1} {{Bob Smith} 25 Audi {Jane Doe} 40 Ford} returns "\{Jane Doe\} 40 Ford \{Bob Smith\} 25 Audi" \(since Smith, which is at index 1 of element 0 of the first group comes after Doe, which is at the same position in the next group of 3.\) # Reference Implementation Available online at <https://sourceforge.net/support/tracker.php?aid=2082681> # Compatibility Since this is a new and unambiguous option, and since the distinction between the options and the list to sort is clear, no compatibility problems are expected. # Limitations Only one element in each group can be used for comparison; it's not possible to compare groups element-by-element. # Further Thoughts There may be some merit in adding a similar option to **lsearch**. The name-value pair case is common enough that an argument could be made for adding **-pairname** and **-pairvalue** options as synonyms for **-stride 2 -index 0** and **-stride 2 -index 1** respectively. # Copyright This document has been placed in the public domain. |
Name change from tip/327.tip to tip/327.md.
|
| < | < | | | | | | | | | > | | | | | | | | | | | | | | | | | < > | < > | | | | | | | | | | | | | | < | > | | | > | 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 | # TIP 327: Proper Tailcalls Author: Miguel Sofer <[email protected]> Author: David S. Cargo <[email protected]> State: Final Type: Project Vote: Done Created: 20-Sep-2008 Post-History: Keywords: tailcall,NRE Tcl-Version: 8.6 ----- # Abstract This TIP recommends adding proper tailcalls to Tcl. # Proposal We propose to add a new command: > **tailcall** _cmd_ ?_arg ..._? The command can only be invoked in a procedure or lambda body. The effect of this command is very similar to: > **return [uplevel 1 [list [namespace which** _cmd_ **]** ?_arg ..._?**]]** with the sole exception that the invocation of _cmd_ happens _after_ the currently executing body returns and is not visible in Tcl's call stack. # Rationale The new Non-Recursive Engine \(NRE\) implemented in Tcl 8.6 allows support for a number of interesting features that have previously been difficult or impossible to implement efficiently in Tcl. One such feature is support for _proper tailcalls_, an important feature for functional-style programming. The new command allows unbounded recursion and enables programming in _continuation passing style_. # Effect on Tcl's Call Stack **tailcall** is implemented as a new command, as opposed to an optimization that would be done automatically by the bytecode compiler, due to the effect it has on Tcl's call stack. Consider the following example: proc showStack {} { set depth [info frame] set res {} for {set i 1} {$i <= $depth} {incr i} { lappend res [info frame $i] } return $res } proc one cmd {join [$cmd] \n} proc two {} {uplevel 1 showStack} proc three {} {tailcall showStack} When run at the interactive prompt, we obtain % one two type eval line 1 cmd {one two} level 2 type proc line -1 cmd {$cmd} proc ::one level 1 type proc line 1 cmd {uplevel 1 showStack} proc ::two type eval line 1 cmd showStack proc ::two type proc line 5 cmd {info frame $i} proc ::showStack level 0 % one three type eval line 1 cmd {one three} level 2 type proc line -1 cmd {$cmd} proc ::one level 1 type proc line 5 cmd {info frame $i} proc ::showStack level 0 % Remark how **tailcall** completely removed the proc _three_ from Tcl's call stack. This effect is also apparent on error traces. # Implementation An experimental implementation of tailcalls is available in Tcl 8.6a2 in CVS on sourceforge, in the ::tcl::unsupported namespace. # Copyright This document has been placed in the public domain. |
Name change from tip/328.tip to tip/328.md.
|
| < | < | | | | | | | | | > | | | | | | | | | | | | | | < > | | | | < > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | < > | | | | | | | | | | | | | | | | | | | | < < > > | | | | | | | | | | < < < > > > | | | | | | < > | | | | < > | | | | | | | | | | | | | | | | | | | | | < < > > | | | | | | | | | | | < | | > | | | | < > | | | < > | | | | | | | | < > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 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 | # TIP 328: Coroutines Author: Miguel Sofer <[email protected]> Author: Neil Madden <[email protected]> State: Final Type: Project Vote: Done Created: 07-Sep-2008 Post-History: Keywords: Coroutine,continuation,event-loop,NRE Tcl-Version: 8.6 ----- # Abstract This TIP recommends adding a coroutine mechanism to Tcl, loosely modelled on those present in Lua. # Rationale The new Non-Recursive Engine \(NRE\) implemented in Tcl 8.6 allows support for a number of interesting features which have previously been difficult or impossible to implement efficiently in Tcl. One such feature is support for _coroutines_, which generalise the notion of subroutine by allowing a command to return multiple times. Conceptually, a coroutine allows a command to suspend its current execution and return \(or _yield_\) a value to its caller. The caller may later _resume_ the coroutine at the point where it previously yielded, allowing it to perform further work and potentially yield further values. Coroutines have applications to a number of areas, in particular they allow a more natural representation of certain programming tasks when using the event loop, such as interacting with a Tk graphical user interface, performing asynchronous remote procedure calls, communicating between threads, and lightweight cooperative multitasking. These use-cases are discussed in more detail in the next section, along with a look at the limitations of the proposed approach, particularly in comparison to the closely related concept of _continuations_. It should be noted that coroutines \(or continuations\) add no extra power to the language. Every computation that can be expressed with corouines can be expressed using existing features of the language by writing code in so-called _continuation-passing style_ \(CPS\), which is the style of code used in loops and other control constructs. Rather, the benefit of coroutines is that it allows certain problems to be expressed more succinctly in cases where the CPS form is tedious to construct, or would require extensive refactoring of existing code. For instance, we can consider the following simple program that asks a user for two numbers and then displays their sum: proc tell msg { puts $msg } proc ask question { puts -nonewline "$question " flush stdout gets stdin } proc main {} { set x [ask "First number:"] set y [ask "Second number:"] tell "Sum = [expr {$x + $y}]" } main In converting this code to work with a Tk GUI or some other asynchronous interface \(such as a Web application\) would generally require restructing the **ask** procedure to take a callback, and then restructuring the main application logic to supply these callbacks. This restructuring when moving from a synchronous to an asynchronous interface hinders such refactoring and also causes the application logic to become fragmented into a number of callback procedures. While anonymous procedures introduced in Tcl 8.5 can mitigate these drawbacks to some extent, there is still some obfuscation of the original code. The coroutine mechanism proposed would allow the interface of the **tell** and **ask** procedures to remain unchanged, and the main application logic to remain identical \(beyond some trivial wrapping\). It is this ability of coroutines to convert synchronous code to work in an asynchronous manner with minimal changes to the application logic that is the main motivating use-case for their consideration. Coroutines can also benefit new asynchronous code that is written from scratch, as the familiar _direct style_ of coding that they enable is clearer to understand in many cases, and to some extent hides the complexity of the underlying asynchronous model. This added expressiveness helps the Tcl programmer to separate logic from control \(Kowalksi, 1979\). The particular style of coroutines proposed are loosely based on the equivalent mechanism implemented in the Lua programming language \(Lua, 2004\). In particular, the coroutines implemented are _asymmetric_ \(yield and resume are separate commands\), and _stackful_ \(yield can be called from any stack depth in the coroutine body\). Asymmetric coroutines \(similar to _generators_\) can simulate symmetric coroutines and vice-versa. # New Commands and Subcommands > **coroutine** _coroCmdName_ **cmd** ?_arg ..._? > **yield** ?_value_? > _coroCmdName_ ?_value_? > **info coroutine** **coroutine** evaluates the Tcl command > **uplevel \#0 [list** _cmd_ ?_arg ..._?**]** until it returns or a yield is encountered. If **yield** is found then a command named _coroCmdName_ will be created with special behaviour as described below. **yield** suspends execution of the coroutine and returns _returnValue_ to the coroutine caller \(not the creator, which may be long dead\) as the return value of the **coroutine** or **coroCmdName** invocation. It is an error to invoke yield outside of a coroutine's body. It is possible to yield from within a nested call, but under some circumstances yield can return an error \(see Limitations\). _coroCmdName_ resumes execution of the suspended coroutine. Execution of the suspended coroutine resumes with returnValue being the return value of the yield that last suspended execution. _coroCmdName_ is garbage-collected: the command and all internal structs are deleted when the coroutine returns. A suspended coroutine is properly cleaned up when its command is rename'd to the empty string. **info coroutine** returns the fully qualified name of the command that will resume the currently executing coroutine if it yields. In other words, it returns _coroCmdName_ when invoked in a suspendable environment, and the empty string otherwise. Whenever **coroCmdName** is invoked and the coroutine itself is running, Tcl's call stack looks exactly as if > **uplevel \#0 [list** _cmd_ ?_arg ..._?**]** had been invoked instead. This structure is properly reflected in **info level**, **info frame** and the error stack. # Use Cases In this section we review a number of motivating use-cases for coroutines. ## Tk Graphical User Interfaces As mentioned in the introduction, one particularly useful application of continuations in Tcl is to allow essentially asynchronous operations, using the event loop, to provide a familiar interface, much like synchronous operations. The example **tell** and **ask** interface can be written using yields to return control temporarily to the event loop until a result is available. This is similar to use of **vwait**, but avoids creating a nested event loop, with all the problems that entails: proc tell msg { tk_messageBox -message $msg } proc ask question { toplevel .ask pack [label .ask.l -text $question] [entry .ask.e] raise .ask; focus .ask.e bind .ask.e <Return> [list apply {cb { set ans [.ask.e get] destroy .ask $cb $ans }} [info coroutine]] yield } # ... main as before ... coroutine main-coro main The original **main** procedure can be reused as-is. The only constraint is that it must be launched as a coroutine using the **coroutine** command. The operation of the code should be straight-forward to understand, as it is mostly standard Tk code. The **ask** command simply creates a Tk dialog box and registers the current coroutine as an event callback for when the user enters a number. Finally the procedure calls **yield** which suspends the current coroutine \(in this case the main procedure\) and allows the event loop to run. Once the user has entered a value and hit Return the coroutine is invoked with the value. This resumes the main procedure, returing this value as the return value of **ask**. From the point of view of the main routine it is as if the ask procedure worked exactly like the synchronous, console-based example. ## Complex Iterators Another common use of coroutines is to support efficient traversal of complex data structures. Here the coroutine is used to implement a stateful _iterator_ for the data structure. In Tcl, one of the most natural and simple ways of writing a traversal interface for a data structure is as a custom control structure or loop. For instance, we can write a simple command for traversing a binary search tree in-order, applying a function to each value: # Constructor functions for our BST proc cons {name args} { proc $name $args { info level 0 } } cons Empty cons Branch left val right proc bst-map {f tree} { if {[lindex $tree 0] eq "Branch"} { bst-map $f [lindex $tree 1] {*}$f [lindex $tree 2] bst-map $f [lindex $tree 3] } } # Print every value in the tree in order bst-map puts $tree While such interfaces are convenient for traversing a single data structure, they are more difficult to use when traversing multiple structures simultaneously, as when merging trees. A coroutine interface allows such custom loops to be easily converted into stateful iterators, allowing a merge to be written in a reasonably straight-forward fashion: proc bst-merge-map {f t1 t2} { set a [coroutine l bst-map yield $t1] set b [coroutine r bst-map yield $t2] while {[valid l] || [valid r]} { if {[valid l] && (![valid r] || $a < $b)} { {*}$f $a; set a [l] } else { {*}$f $b; set b [r] } } } proc valid cmd { llength [info commands $cmd] } bst-merge-map puts $t1 $t2 The benefit here is that the simple single-tree traversal function can be reused for merging multiple trees, simply by wrapping it in a coroutine. ## Asynchronous Communications Similar to the use of coroutines for event-based GUI programming, we can also use the mechanism for asynchronous networking, such as fetching data over HTTP, making remote procedure calls, and message-passing between threads. For example, asynchronous HTTP requests become as simple as synchronous ones: proc get url { http::geturl $url -command [info coroutine] yield } proc main {} { set t [get http://wiki.tcl.tk/4] puts [http::data $t] http::cleanup $t } coroutine m main This common pattern of registering the current coroutine as a callback and then yielding can be used to accomplish a wide variety of such tasks. # Limitations The coroutine implementation depends on the NRE enhancements recently made to the Tcl core. In particular, in order to capture a coroutine it is essential that all commands currently on the evaluation stack are NRE-aware. This is the case for most core Tcl commands, but at the time of writing few extensions will have made this transition. In these cases, trying to capture a coroutine while in an evaluation context containing a non-NRE-aware C command will result in an error. This situation is currently unavoidable, but we believe that it will improve over time as extensions are adapted to take advantage of the new features that NRE enables. In the meantime, the coroutine mechanism is still useful in a wide variety of situations, and the cases where it is not applicable should be easy to detect, as the code will fail immediately on trying to capture a coroutine. Nevertheless, library writers should be aware of the situation and avoid over reliance on coroutines. It is easy to wrap coroutine interfaces around existing callback-based library routines \(as in the HTTP example\). Coroutines are roughly equivalent in expressive power to _one-shot continuations_. A continuation is simply a function that represents the rest of a computation. Continuations can be explicitly created, as in continuation- passing style \(CPS\) code, but some languages \(notably Lisp and Scheme\) allow the current execution context to be automatically captured as a continuation with a similar effect to coroutines. Such continuations can either be invoked once \(a one-shot continuation\) or several times \(multi-shot\). One-shot continuations can be used for much the same tasks that we have identified in this TIP, and can also be used to implement coroutines. Coroutines can likewise implement one-shot continuations. Multi-shot continuations, however, are strictly more expressive than either coroutines or one-shot continuations as they allow the same continuation to be resumed multiple times. In contrast, when a coroutine yields it can only be resumed once, and then must call yield again. An example of a construct that cannot be implemented using coroutines is a nondeterministic choice operator: set x [choose 1 2 3 4] set y [choose 3 9 7] if {$x**2 != $y} { fail } puts "x=$x,y=$y" Intuitively, we would like this code to eventually succeed with values _x = 3_ and _y = 9_. However it is not possible to implement **choose** using coroutines as we can only yield from inside the choose statement once, and then are forced to yield instead from within **fail**, which is incorrect. A multi-shot continuation is capable of implementing **choose** as it can resume the _same_ continuation multiple times with different values, essentially allowing the code to jump back to the appropriate choose statement for each back-track. While a non-deterministic choice operator is an interesting use-case, it is not considered a primary motivation for this TIP. Such nondeterministic searches can be implemented using loops or custom control structures and exceptions \(this essentially amounts to using CPS\). For instance: foreach x {1 2 3 4} { foreach y {3 9 7} { if {$x**2 == $y} { puts "x=$x,y=$z" } } } Furthermore, support for multi-shot continuations is believed to be more expensive to implement than coroutines, as the execution environment has to be copied for each continuation point, whereas a coroutine reuses the same environment for multiple yield/resume pairs. It is believed that the vast majority of useful use-cases will fall into the expressive power of coroutines. However, this limitation is real and should be taken into account when considering this TIP. A final apparent limitation of the proposed mechanism is that it only supports passing a single argument when resuming a coroutine. The reason for this is simply that **yield** only returns a single result, and so a single argument is all that is required. It is believed that this will be sufficient for the majority of use-cases. However, in cases where multiple arguments are required, it is straight-forward to wrap the coroutine resume command so that these are passed as a list: proc resume {coro args} { $coro $args } The coroutine body can then use **lassign**, **lindex** or some other means to extract the arguments. This can be used, for instance, when using a coroutine for variable tracing, such as in Colin Macleod's coroutine-enabled version of **vwait** that avoids nesting event loops <http://wiki.tcl.tk/21555> : proc co_vwait varName { upvar $varName var set callback [list resume [info coroutine]] trace add variable var write $callback yield trace remove variable var write $callback } Along similar lines, the **yield** and _coroCmdName_ commands currently do not offer support for communicating exceptions to/from coroutines. As with multiple arguments, this can be addressed by passing a dictionary of options \(as produced by **catch**\) as well as a value: proc exyield {value args} { lassign [yield [list $value $args]] value opts return -options $opts $value } proc exresume {coro value args} { lassign [$coro [list $value $args]] value args return -options $opts $value } # Usage proc mycoro {} { exyield $val -code error -errorcode $somecode ... } It is expected that such wrappers can be added to Tcllib for now. Adding support for these options directly to the yield and resume command interfaces could be done in the future by a further TIP, if the functionality is deemed sufficiently critical. # Alternatives An alternative syntax for coroutines is described in \(Lua, 2004\) based on a symmetric **yield** command. In this approach, **yield** takes as an extra argument the name of a coroutine to pass control to, rather than implicitly transferring control back to the caller. This eliminates the need for a separate _resume_ interface \(the _coroCmdName_ in the current TIP\). However, we believe that the asymmetric interface is more intuitive for most tasks, and the fact that coroutines are stateful entities requires them to have some named representation in any case, so this may as well be used as a resume command. It is possible to simulate symmetric coroutines with the current proposal using a simple loop: proc run-coros {coro value} { while 1 { lassign [$coro $value] coro value } } proc symyield {coro value} { yield [list $coro $value] } An alternative to a coroutine mechanism would be to adopt some form of _continuations_ into Tcl. As described previously, a continuation is a command that captures the current state of a computation \(i.e. the current control stack and execution environment\) and saves it so that it can be resumed later. In this respect, a continuation is similar to a coroutine. There are a number of varieties of continuations described in the literature \(see <http://library.readscheme.org/page6.html> for a collection of references\), with different expressive powers. _Escape continuations_ only allow jumping to a context which is still on the stack. Such continuations are equivalent in power to exceptions, which Tcl already has. _One-shot_ continuations can only be resumed once and are then discarded. As previously stated, such continuations are equivalent to coroutines as any particular **yield** can only be resumed once. _Multi-shot_ continuations allow the same continuation to be resumed multiple times. These continuations go beyond the power of coroutines, and allow examples such as the nondeterministic choice operator to be implemented. Multi-shot continuations are however rather more expensive to implement, as each yield point requires creating a fresh copy of the execution environment, whereas a coroutine can reuse the same environment copy for multiple yield/resumes as it knows it cannot be resumed more than once for a single yield. A further refinement is the idea of _delimited continuations_ which capture only a certain portion of the execution context \(stack\), rather than everything. Delimited continuations can simulate normal continuations by simply capturing the entire dynamic extent, but they have the advantage that they can also return a value, allowing them to be composed. Coroutines are also of this form, where the extent of the coroutine is limited to where the **coroutine** command was originally called from. The coroutine mechanism proposed is therefore of roughly equivalent power to a _one-shot delimited continuation_. Such a mechanism is strictly less powerful than a multi-shot continuation implementation, but it is believed that it is sufficient to cover the vast majority of useful use-cases, while remaining relatively simple to understand, and efficient to implement. Lars Hellström has also proposed an alternative control mechanism for Tcl \(Hellström, 2008\), which is essentially a form of multi-shot full \(non delimited\) continuation, based on an interface of two commands: **suspend** and **resume**. The **suspend** command captures the current evaluation context into a continuation and then throws this as an exception with a special TCL\_SUSPEND return code, allowing it to be caught and later resumed. The interface supports communicating values and exceptions to the resumed continuation. While the interface is potentially more expressive than the coroutine mechanism here, the proposed implementation involves destroying the stack as it is captured when the TCL\_SUSPEND exception propagates. This presents a number of practical problems, such as the destruction of local variables \(and thus the firing of unset traces\), and the overall inefficiency of the approach. As coroutines thus captured are stateless objects they can be implemented as plain Tcl values \(i.e., strings\), albeit potentially quite large and complex ones. This provides the usual advantages of easy serialisation and transfer, while suffering the usual drawbacks of lack of encapsulation \(potentially exposing implementation details\) and potential inefficiencies due to shimmering or excess copying of data \(a general problem of multi-shot continuations\). While some of these problems can be limited or overcome entirely, it is our view that the current coroutines proposal covers a great deal of the expected use-cases in a much simpler and more efficient manner. # Implementation An experimental implementation of the coroutine mechanism is available in Tcl 8.6a2 in CVS on sourceforge. The implementation is available in the ::tcl::unsupported namespace, exposing the _coroutine_, _yield_, and _infoCoroutine_ commands. # References \(Kowalski, 1979\) Robert Kowalski, "Algorithm = logic \+ control", _Communications of the ACM_ 22\(7\), pp. 424-436, 1979. \(Lua, 2004\) Ana Lûcia De Moura, Roberto Ierusalimschy, "Revisting Coroutines", Tech Report, 2004. <http://www.inf.puc-rio.br/~roberto/docs/MCC15-04.pdf> \(Hellström, 2008\) Lars Hellström, "Suspend and Resume", <http://wiki.tcl.tk/21537> # Copyright This document has been placed in the public domain. |
Name change from tip/329.tip to tip/329.md.
|
| < | < | | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | < > | | | | < > | | < | > | | | | | | | < > | | | | | | < < > > | | | | | | | | | | | | | > | 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 | # TIP 329: Try/Catch/Finally syntax Author: Trevor Davel <[email protected]> State: Final Type: Project Vote: Done Created: 22-Sep-2008 Post-History: Discussions-To: http://wiki.tcl.tk/21608 Obsoletes: 89 Tcl-Version: 8.6 ----- # Abstract This TIP proposes the addition of new core commands to improve the exception handling mechanism. It supercedes [[89]](89.md) by providing support for the error options dictionary introduced in Tcl 8.5 by [[90]](90.md). # Rationale See [[89]](89.md) for general rationale for enhancing exception handling. The **try** syntax presented here is not intended to replace **catch**, but to simplify the expression of existing exception/error handling techniques, leading to greater code clarity and less error-prone workarounds for **finally** blocks. There is no deficiency in the functionality of Tcl's exception handling mechanisms - what is lacking is a more readable syntax and a standard for behaviour across packages for the common case of catching a subset errors or exceptions that are thrown from within a particular block of code. In Tcl 8.4 exceptions could be caught using **catch**, and exception information was available via the **catch** return value and resultvar. If the return value was TCL\_ERROR \(1\) then the globals **::errorCode** and **::errorInfo** would be set according to the exception raised. [[89]](89.md) was written to work with this model, such that a catch handler \(in a **try...catch**\) would be able to capture the resultvar, errorCode and errorInfo. Tcl 8.5 implements [[90]](90.md) which extends **catch** to allow an additional dictionary of options \(error information\) to be captured. These options supercede the **::errorInfo** and **::errorCode** globals \(though those are still supported for backward compatibility\). It is therefore logical to extend/correct the syntax of [[89]](89.md) to support the options dictionary in preference to the older mechanism for capturing exception information. Benefits of adding this functionality to the core: * Bring to Tcl a construct commonly understood and widely used in other languages. * A standard for identifying categories/classes of errors, which will improve interoperability between packages. * A byte-coded implementation would be significantly faster than the Tcl implementation that is presented. # Specification > **try** _body_ ?_handler_ ...? ?**finally** _body_? > **throw** _type message_ The **try** body is evaluated in the caller's scope. The handlers are searched in order of declaration until a matching one is found, and the associated body is executed. If no matching handler is found then **try** returns the result of the **try** body \(exceptions will propagate up the stack as usual\); otherwise **try** returns the result of the handler body \(exceptions will propagate up the stack as usual\). Only one handler body \(that of the first matching handler\) will be executed. If the handler body is the literal string "**-**" then the body for the subsequent handler will be used instead. It is an error for the last handler's body to be a literal "**-**". The **finally** body \(if present\) will be executed last, and is always executed whatever the results of the try and handler bodies \(excepting resource exhaustion or cancellation\). If the **finally** body returns an exceptional code then this will become the result of **try**, otherwise the result of the **finally** body is ignored. Since the **trap** handlers in the **try** control structure are filtered based on the exception's **-errorcode**, it makes sense to have a command that will encourage the use of error codes when throwing an exception. **throw** is merely a reordering of the arguments of the **error** command. _type_ is treated as a list by **trap** \(see below\), which maintains compatibility with the description of ::errorCode given in **tclvars**. ## Handlers Each handler is identified by a keyword. The fields following the keyword indicate what exceptions or errors are matched by the handler, the variables into which the result of the **try** body will be assigned \(in the caller's scope\), and the body of the handler. > **on** _code \{?resultVar ?optionsVar?\} body_ The **on** handler allows exact matching against the exceptional return code \(the integer value that would be returned by **catch**\). The _code_ may be given as an integer or one of the magic keywords **ok** \(0\), **error** \(1\), **return** \(2\), **break** \(3\), **continue** \(4\). > **trap** _pattern \{?resultVar ?optionsVar?\} body_ The **trap** handler allows list prefix matching against the **-errorcode** from the options when the exceptional return code is TCL\_ERROR \(1\). Given a _pattern_ and an _errorcode_, a list prefix match is successful if for every element in _pattern_ there is a corresponding and identical element in _errorcode_. Trailing elements in _errorcode_ are ignored. Notes & clarifications: * Handlers are searched in order of declaration \(left-to-right\). One consequence of this search order is that an **on error** handler will supercede all subsequent **trap** handlers. * Any unhandled exception propagates. * The result of the last executed body \(other than the **finally** body\) is the result of the **try**. Exceptions in any _handler_ body or in the **finally** replace the existing exception and propagate. * If any exception is replaced \(by an exception in a handler body or in the **finally** body\) then the new exception shall introduce into its options dictionary the field **-during** that contains the options dict of the exception that was replaced. * If any errorcode happens to be not a list, a **trap** handler will be unable to process it. However, this should only happen in cases where there is a bug or other problem elsewhere, since **return** is documented to require the errorcode to be a list. # Examples Simple example of **try**/_handler_/**finally** logic in Tcl using currently available syntax: proc read_hex_file {fname} { set f [open $fname "r"] set data {} set code [catch { while { [gets $f line] >= 0 } { append data [binary format H* $line] } } em opts] if { $code != 0 } { dict set opts -code 1 set em "Could not process file '$fname': $em" } close $f return -options $opts $em } And the same example rewritten to use [**try**]: proc read_hex_file {fname} { set f [open $fname "r"] set data {} try { while { [gets $f line] >= 0 } { append data [binary format H* $line] } } trap {POSIX} {} { puts "POSIX-type error" } on error {em} { error "Could not process file '$fname': $em" } finally { close $f } } This illustrates how the intent of the code is more clearly expressed by [**try**]. # References * Tcl 8.4 catch <http://www.tcl.tk/man/tcl8.4/TclCmd/catch.htm> * Tcl 8.5 catch <http://www.tcl.tk/man/tcl8.5/TclCmd/catch.htm> # Rejected Alternatives Various alternatives are discussed on the wiki <http://wiki.tcl.tk/21608> along with reasons for their rejection. # Future Extensions No specific future exceptions are planned, but **try** could be extended by adding new handler keywords and/or introducing new varnames to the variables list that is associated with each handler. It is recommended that new handlers maintain the established convention: > **keyword** _criteria \{?resultVar ?optionsVar?\} body_ # Reference Implementation A reference implementation can be found at <http://www.crypt.co.za/pub/try-1.tcl> # Thanks Thanks in particular to DKF, NEM and JE for their feedback and suggestions on this TIP. # Copyright This document has been placed in the public domain. |
Name change from tip/33.tip to tip/33.md.
|
| < | < | | | | | | | | > | | | | | | | | | | | | | < > | < | > | | | | | | | | | | | | | | | | | | < > | < | > | | | | | | | | | | | | | | | | | | | | | | | | < | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | < > | < > | | | | | | | | | | | | | < > | | | | | | | | | | | | | | | | < > | | | | | | | < > | | | | | < > | | | | | | | | | | | | | | | | < > | | | | | | < > | | | | | | | < > | | | | | < > | | | | | | | | | | | | < > | | < > | | < > | | | | | | < > | | | | | | | < > | | | | < > | | | | | | | | | | < > | | | | | | | | | | < > | | | | < < > > | | | | | | | | | | | | < < > > | | | | | | | | | | | | | | | | | | | < > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | < > | | | < > | < > | | | | | | | | | | | < > | | | | | | | | | | | | | < < < > > > | | < | > | | | | | | | | | | | | | | | | < | > | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 | # TIP 33: Add 'lset' Command to Assign to List Elements. Author: Kevin Kenny <[email protected]> State: Final Type: Project Vote: Done Created: 15-May-2001 Post-History: Discussions-To: news:comp.lang.tcl,mailto:[email protected] Tcl-Version: 8.4 ----- # Abstract Most popular programming languages provide some sort of indexed array construct, where array subscripts are integers. Tcl's lists are implemented internally as indexed arrays, but it is difficult to use them as such because there is no convenient way to assign to individual elements. This TIP proposes a new command, _lset_, to rectify this limitation. # Rationale The implementation of lists in Tcl has evolved far beyond the original conception. While lists were originally conceived to be strings with a particular syntax that allowed them to be parsed as lists, the internal representation of a list is now an array of pointers to _Tcl\_Obj_ structures. Tcl programmers, for the most part, have not taken advantage of this evolution. Code that uses hash tables where linear arrays would be a more appropriate structure is still extremely common. Moreover, it is difficult to update lists in place, even if their internal representations are known not to be shared. One example of this difficulty is seen in the discussions <http://purl.org/thecliff/tcl/wiki/941> of how best to shuffle a list of items. The discussion began with a naïve implementation of Jon Bentley's method of performing random swaps: proc shuffle1 { list } { set n [llength $list] for { set i 0 } { $i < $n } { incr i } { set j [expr {int(rand()*$n)}] set temp [lindex $list $j] set list [lreplace $list $j $j [lindex $list $i]] set list [lreplace $list $i $i $temp] } return $list } Aside from the fact that the syntax obscures what the program is doing, the implementation suffers from an obscure performance problem. When the _lreplace_ calls in the _shuffle1_ procedure are executed, the internal representation of _list_ has two references: the value of the variable, and the parameter passed to _lreplace_. The multiple references force _lreplace_ to copy the list, leading to quadratic performance when large lists are shuffled. It is possible, albeit difficult, to alleviate this problem by careful management of the lifetime of _Tcl\_Obj_ structures, but this change complicates the code. The simplest way to fix the performance is probably to use Donal Fellows's implementation of the _K_ combinator: proc K { x y } { set x } which allows the caller of _lreplace_ to extract the value of _list_, change the value of _list_ so that the extracted value is unshared, and then pass the extracted value as a parameter to _lreplace:_ proc shuffle1a { list } { set n [llength $list] for { set i 0 } { $i < $n } { incr i } { set j [expr {int(rand()*$n)}] set temp1 [lindex $list $j] set temp2 [lindex $list $i] set list [lreplace [K $list [set list {}]] $j $j $temp2] set list [lreplace [K $list [set list {}]] $i $i $temp1] } return $list } Now the performance of the code is _O\(n\)_ where _n_ is the length of the list, but the programmer's intent has been seriously obscured! Moreover, the performance is still rather poor: Tcl makes an atrocious showing, for instance, in Doug Bagley's 'Great Computer Language Shootout' <http://www.bagley.org/~doug/shootout/> . # Specification This TIP proposes an 'lset' command with the syntax: lset varName indexList value or lset varName index1 index2... value where: > _varName_ is the name of a variable in the caller's scope. > If _objc==4_, then the _indexList_ parameter is interpreted as a list of _index_ arguments; if _objc>4_, then the _index_ arguments are inline on the command line. > In either case, Each _index_ argument is an index in the content of _varName_ or one of its sublists \(see below\). The format of _index_ is either an integer whose value is at least zero and less than the length of the corresponding list, or else the literal string _end_, optionally followed with a hyphen and an integer whose value is at least zero and less than the length of the corresponding list. > _value_ is a value that is to be stored as a list element. The return value of the command, if successful, is the new value of _varName._ The simplest form of the command: lset varName index value replaces, in place, the _index_ element of _varName_ with the specified _value_. For example, the code: set x {a b c} lset x 1 d results in _x_ having the value _a d c_. The result, except for performance considerations and the details of error reporting, is roughly the same as the Tcl code: proc lset { varName index value } { upvar 1 $varName list set list [lreplace $list $index $index $value] return $list } except that where the _lreplace_ command permits indices outside the existing list elements, the proposed _lset_ command forbids them. If multiple _index_ arguments are supplied to the _lset_ command, they refer to successive sublists in a hierarchical fashion. Thus, lset varName $i $j value or, equivalently, lset varName [list $i $j] value asks to change the value of the _j_th element in the _i_th sublist of _varName_. Hence, the code: set x {{a b c} {d e f} {g h i}} lset x 1 1 j; # -or- lset x {1 1} j changes the value of _x_ to {a b c} {d j f} {g h i} and the code set y {{{a b} {c d}} {{e f} {g h}}} lset y 1 0 1 i; # -or- lset y {1 0 1} i changes the value of _y_ to {{a b} {c d}} {{e i} {g h}} This notation also dovetails prettily with the extension of the _lindex_ command proposed in [[22]](22.md). The command lindex $y 1 0 1; # -or- lindex y {1 0 1} will extract the element that is set by the command lset $y 1 0 1 $value The _lset_ command will throw an error and leave the variable unchanged if it is presented with fewer than three arguments, if any of the _index_ arguments is out of range or ill-formed, or if any of the data being manipulated cannot be converted to lists. It will throw an error after modifying the variable if any write trace on the variable fails. With the proposed _lset_ command, the procedure to shuffle a list becomes much more straightforward: proc shuffle1b { list } { set n [llength $list] for { set i 0 } { $i < $n } { incr i } { set j [expr {int(rand()*$n)}] set temp [lindex $list $j] lset list $j [lindex $list $i] lset list $i $temp } return $list } The given implementation copies the list only once, the first time that the line: lset list $j [lindex $list $i] is executed. Thereafter, the list is an unshared object, and the replacements are performed in place. # Reference Implementation The author has implemented a simpler variant of the proposed command as an object command, and also proposes to bytecode compile it, although the implementation of bytecode compilation is incomplete. The reference implementation also does not yet expand _objv[[2]](2.md)_ as a list in the case where _objc==4,_ and is known to have memory leaks where ill-formed index arguments are presented. It is given here as _concept code_ and to present its impact on performance of some common list operations. \(Obviously, it will be completed and reviewed with the relevant maintainers prior to being committed to the Core.\) The core of the implementation is the following procedure: int Tcl_LsetObjCmd( clientData, interp, objc, objv ) ClientData clientData; /* Not used. */ Tcl_Interp *interp; /* Current interpreter. */ int objc; /* Number of arguments. */ Tcl_Obj *CONST objv[]; /* Argument values. */ { Tcl_Obj* listPtr; /* Pointer to the list being altered. */ Tcl_Obj* subListPtr; /* Pointer to a sublist of the list */ Tcl_Obj* finalValuePtr; /* Value finally assigned to the variable */ int index; /* Index of the element being replaced */ int result; /* Result to return from this function */ int listLen; /* Length of a list being examined */ Tcl_Obj** elemPtrs; /* Pointers to the elements of a * list being examined */ int i; /* Check parameter count */ if ( objc < 4 ) { Tcl_WrongNumArgs( interp, 1, objv, "listVar index ?index...? value" ); return TCL_ERROR; } /* Look up the list variable */ listPtr = Tcl_ObjGetVar2( interp, objv[ 1 ], (Tcl_Obj*) NULL, TCL_LEAVE_ERR_MSG ); if ( listPtr == NULL ) { return TCL_ERROR; } /* Make sure that the list value is unshared. */ if ( Tcl_IsShared( listPtr ) ) { listPtr = Tcl_DuplicateObj( listPtr ); } finalValuePtr = listPtr; /* * If there are multiple 'index' args, handle each arg except the * last by diving into a sublist. */ for ( i = 2; ; ++i ) { /* Take apart the list */ result = Tcl_ListObjGetElements( interp, listPtr, &listLen, &elemPtrs ); if ( result != TCL_OK ) { return result; } /* Derive the index of the requested sublist */ result = TclGetIntForIndex( interp, objv[i], (listLen - 1), &index ); if ( result != TCL_OK ) { return result; } if ( ( index < 0 ) || ( index >= listLen ) ) { Tcl_SetObjResult( interp, Tcl_NewStringObj( "list index out of range", -1 ) ); return TCL_ERROR; } /* Break out of the loop if we've extracted the innermost sublist. */ if ( i >= ( objc - 2 ) ) { break; } /* * Extract the appropriate sublist, and make sure that it is unshared. */ subListPtr = elemPtrs[ index ]; if ( Tcl_IsShared( subListPtr ) ) { subListPtr = Tcl_DuplicateObj( subListPtr ); result = Tcl_ListObjSetElement( interp, listPtr, index, subListPtr ); if ( result != TCL_OK ) { return TCL_ERROR; } } else { Tcl_InvalidateStringRep( listPtr ); } listPtr = subListPtr; } /* Store the result in the list element */ result = Tcl_ListObjSetElement( interp, listPtr, index, objv[objc-1] ); if ( result != TCL_OK ) { return result; } /* Finally, update the variable so that traces fire. */ listPtr = Tcl_ObjSetVar2( interp, objv[1], NULL, finalValuePtr, TCL_LEAVE_ERR_MSG ); if ( listPtr == NULL ) { return TCL_ERROR; } Tcl_SetObjResult( interp, listPtr ); return result; } The procedure depends on a new service function, _Tcl\_ListObjSetElement_: int Tcl_ListObjSetElement( interp, listPtr, index, valuePtr ) Tcl_Interp* interp; /* Tcl interpreter; used for error reporting * if not NULL */ Tcl_Obj* listPtr; /* List object in which element should be * stored */ int index; /* Index of element to store */ Tcl_Obj* valuePtr; /* Tcl object to store in the designated * list element */ { int result; /* Return value from this function */ List* listRepPtr; /* Internal representation of the list * being modified */ Tcl_Obj** elemPtrs; /* Pointers to elements of the list */ int elemCount; /* Number of elements in the list */ /* Ensure that the listPtr parameter designates an unshared list */ if ( Tcl_IsShared( listPtr ) ) { panic( "Tcl_ListObjSetElement called with shared object" ); } if ( listPtr->typePtr != &tclListType ) { result = SetListFromAny( interp, listPtr ); if ( result != TCL_OK ) { return result; } } listRepPtr = (List*) listPtr->internalRep.otherValuePtr; elemPtrs = listRepPtr->elements; elemCount = listRepPtr->elemCount; /* Ensure that the index is in bounds */ if ( index < 0 || index >= elemCount ) { if ( interp != NULL ) { Tcl_SetObjResult( interp, Tcl_NewStringObj( "list index out of range", -1 ) ); return TCL_ERROR; } } /* Add a reference to the new list element */ Tcl_IncrRefCount( valuePtr ); /* Remove a reference from the old list element */ Tcl_DecrRefCount( elemPtrs[ index ] ); /* Stash the new object in the list */ elemPtrs[ index ] = valuePtr; /* Invalidate and free any old string representation */ Tcl_InvalidateStringRep( listPtr ); return TCL_OK; } Even without bytecode compilation, the performance improvement of array-based applications that can be achieved by the _lset_ command is substantial. The following table shows run times in microseconds \(on a 550 MHz Pentium III laptop, running a modified Tcl 8.4 on Windows NT 4.0, Service Pack \#6\) of the three implementations of _shuffle_ that appear in this TIP. RUN TIMES IN MICROSECONDS Version shuffle1 shuffle1a shuffle1b (Naive) (K combinator) (lset command) List length 1 26 32 27 10 108 152 101 100 1627 1462 936 1000 117831 14789 9574 10000 Test stopped 152853 96912 Similar \(30-50%\) improvements are observed on many of the array related benchmarks that have been proposed. Bytecode compilation is expected to produce even greater improvements. Another area where _lset_ can achieve a major performance gain is in memory usage. The author of this TIP has benchmarked competing implementations of heapsort, one using Tcl arrays, and the other using _lset_ to manipulate lists as linear arrays. When sorting 80000 elements, the Tcl-array-based implementation used 12.7 megabytes of memory; the list-based implementation was faster and used only 5.6 megabytes. The explanation is simple: each entry in the hash table requires an allocated block of twenty bytes of memory, plus the space required for the hash key. The hash key is a string, and requires at least six bytes. When both of these objects are aligned and padded with the overheads imposed by _ckalloc_, they require about 80 bytes of memory on the Windows NT platform. The memory cost of an element of a Tcl list, by comparison, is four bytes to hold the pointer to the object. # Discussion There are several objections that can be foreseen to this proposal. * _Why implement the command in the Core and not as an extension?_ > In a word, _performance._ At the present state of Tcl development, only Core commands can be bytecoded. The cost of the hash table lookups in the _Tcl\_ObjGetVar2_ and _Tcl\_ObjSetVar2_ calls is significant, and can be eliminated from many common usages by the bytecode compiler. Since this command is likely to appear in inner loops, it is important to squeeze every bit of possible performance out of it. * _Why a new command in the global namespace?_ > The author of this TIP feels that having a single added command that is parallel to the existing list commands is not polluting the namespace excessively. It would be a shame if this proposal founders upon the Naming of Names. * _Why a new command, rather than including this functionality in the proposed functionality of an extensible command for list manipulation?_ > The author of this TIP has yet to see a formal proposal of any extensible list manipulation command; the closest thing appears to be Andreas Kupries's _listx_ package <http://www.oche.de/~akupries/tcltk.html> . Given the size and complexity of any such modification, it is unlikely that it will be available in the Core in time for an 8.4 release. The performance improvements achievable by the _lset_ command are needed urgently. * _Isn't this [[29]](29.md) warmed over?_ > Several objectors to [[29]](29.md) indicated that they were willing to consider list element assignment implemented as a new command. * _Doesn't this proposal depend on multiple _index_ arguments to _lindex_ \([[22]](22.md)\)? > This proposal can stand alone. If multiple _index_ arguments to _lindex_ are also accepted, the resulting symmetry is pleasing. Having multiple _index_ args to _lset_ is much more important, because it is horribly difficult to implement equivalent functionality in pure Tcl without introducing excessive calls to _Tcl\_DuplicateObj_. In fact, the reference implementation of _lset_ presented in this TIP was motivated by the fact that its author gave up on the task and resorted to C. # Implementation Notes Having two versions of the syntax for the _lset_ command is perhaps unattractive, but neither can be left out effectively. The syntax where the indices are packaged as a single list allows a _cursor_ into complex list structure to be maintained in a single variable. The list element that the cursor designates can be altered with a single call to the _lset_ command, without needing to resort to _eval_ \(a command that is both expensive and dangerous\) to expand the indices inline. The syntax where each index is a first-class object is motivated by the performance of array-based algorithms. Programmers who are using lists as arrays know exactly how many subscripts they have, and in fact are generally iterating through them. A typical sort of usage might be the naïve matrix multiplication shown below. # Construct a matrix with 'rows' rows and 'columns' columns # having an initial value of 'initCellValue' in each cell. proc matrix { rows columns { initCellValue {} } } { set oneRow {} for { set i 0 } { $i < $columns } { incr i } { lappend oneRow $initCellValue } set matrix {} for { set i 0 } { $i < $rows } { incr i } { lappend matrix $oneRow } return $matrix } # Multiply two matrices proc matmult { x y } { set m [llength $x]; # Number of rows of left matrix set n [llength [lindex $x 0]]; # Number of columns of left matrix if { $n != [llength $y] } { return -code error "rank error: left operand has $n columns\ while right operand has [llength $y] rows" } set k [llength [lindex $y 0]]; # Number of columns of right matrix # Construct a matrix to hold the product set product [matrix $m $k] for { set i 0 } { $i < $m } { incr i } { for { set j 0 } { $j < $k } { incr j } { lset product $i $j 0.0 for { set r 0 } { $r < $n } { incr r } { set term [expr { [lindex $x $i $r] * [lindex $y $r $j] }] lset product $i $j [expr { [lindex $product $i $j] + $term }] } } } return $product } Note how we have an [lset] operation in the innermost loop, executed \(m\*n\*k\) times. If in this instance, we have to write: set indices [list $i $j] lset product $indices \ [expr { [lindex $product $indices] + $term }] in place of the [lset] shown above, we add the cost of forming the list of indices to the cost of the inner loop. This cost is not to be sneezed at -- it's two expensive calls to _ckalloc._ \(The cost can be avoided, at some cost in readability, by maintaning a variable containing the index list, and altering its elements with other uses of [lset].\) Richard Suchenwirth suggested the compromise that appears in this proposal. This scheme will perilous to performance if implemented naively. If the implementation of [lset] simply calls _Tcl\_ListObjGetElements_, look what happens to the inner loop of our _shuffle1b_ procedure: for { set i 0 } { $i < $n } { incr i } { set j [expr {int(rand()*$n)}] set temp [lindex $list $j] lset list $j [lindex $list $i] lset list $i $temp } * Initially, \{set i 0\} sets i to the constant "0"; it is a string. * Evaluating the conditional \{$i < $n\} will shimmer i to an integer; now it's an integer. \(We had to do a call to strtol here.\) * The [lindex $list $i] call now has to consider $i as a list of indices, and shimmers it to the list. This discards the internal rep, parses the string rep into a list, and then reconverts its first element to an integer. * OK, now the 'lset' is happy, and no further shimmering occurs... * ... until we get to the \{incr i\}. Now we go back to the string rep once again, shimmer it to an integer \(yet another call to strtol\), and invalidate the string rep because we've incremented the integer. * Now we get back into the [lindex] once again, and need a list rep. This time, we have to format the integer as a string, parse it as a list, take the object representing element 0, and reparse that as an integer. This sequence has converted the integer to and from a string, and performed four calls to _ckalloc_, but resulted in the same integer that we started with! It is possible for a sufficiently smart compromise implementation to avoid all this shimmering. In the case where _objc==4_, the _lset_ command must: 1. Test whether _objv[[2]](2.md)_ designates an object whose internal representation holds an integer. If so, simply use it as an index. 2. Test whether _objv[[2]](2.md)_ designates an object whose internal representation holds a list. If so, perform the recursive extraction of indexed elements from sublists described above. 3. Form the string representation of _objv[[2]](2.md)_ and test whether it is _end_ or _end-_ followed by an integer. If so, use it as an index. 4. Attempt to coerce _objv[[2]](2.md)_ to an integer; if successful, use the result as an integer. 5. Attempt to coerce _objv[[2]](2.md)_ to a list; if successful, use the result as an index list. 6. Report a malformed _index_ argument; the _indexList_ parameter is not a well-formed list. This logic handles all the cases of singleton lists transparently; it is effectively a simple-minded type inference that optimizes away needless conversions. With it in place, none of the _lset_ examples shown in this TIP will suffer from type shimmering. In the event that the related [[22]](22.md) is approved, the logic for parsing an index list will likely be combined with that used in the _lindex_ command. Bytecoding variadic commands like _lset_ presents some interesting technical challenges; a discussion in progress on the Tcl'ers Wiki <http://wiki.tcl.tk/1604> is recording the design decisions being made for bytecoding _lset_ so that they can be applied to similar commands in the future. # See Also [[22]](22.md), [[29]](29.md). # Change History This TIP has undergone several revisions by the original author. The most significant was made on 20 May 2001, where the syntax was revised to allow for either several indices inline on the command line or a list of indices. # Copyright This document has been placed in the public domain. |
Name change from tip/330.tip to tip/330.md.
|
| < | < | | | | | | | > | | | | | | | | | | | | | > | 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 | # TIP 330: Eliminate interp->result from the Public Headers Author: Kevin B. Kenny <[email protected]> State: Final Type: Project Vote: Done Created: 22-Sep-2008 Post-History: Tcl-Version: 8.6 ----- # Abstract This TIP proposes to eliminate the long-deprecated _interp_->_result_ field from the public headers. # Proposal The include file _tcl.h_ is to be modified so that the _result_ field of the _Tcl\_Interp_ data structure will be renamed to _unused1_ unless a preprocessor symbol, **USE\_INTERP\_RESULT** is defined. Note that this change leaves the _result_ field in the internal _Interp_ data structure untouched, and all the code that manipulates it will still be there. Stubs compatiblity is thus preserved for extensions that compile against an 8.5 or earlier code base, and full source-level compatibility is available with the appropriate preprocessor definition. # Rationale The _result_ field in this structure has been deprecated for a decade now, and yet extensions that use it still turn up. Extension writers need to be put on sterner notice that it _will_ disappear as soon as Tcl 9.0 development is open. # Copyright Copyright © 2008 by Kevin B. Kenny. This document may be distributed subject to the terms and conditions set forth in the Open Publication License, version 1.0 <http://www.opencontent.org/openpub/> . |
Name change from tip/331.tip to tip/331.md.
|
| < | < | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 331: Allow [lset] to Extend Lists Author: Kevin B. Kenny <[email protected]> State: Final Type: Project Vote: Done Created: 22-Sep-2008 Post-History: Tcl-Version: 8.6 ----- # Abstract This TIP proposes to modify the **lset** command to allow it to extend lists. # Proposal The **lset** command shall be modified to allow the index _end\+1_ \(or any equivalent index designating the element one beyond the last element of the list\). For the simple usage: lset list end+1 foo the effect is the same as if the script had evaluated the command: lappend list foo For the usage: lset list $n end+1 foo the effect is much the same as if the script had evaluated: set temp [lindex $list $n] lappend temp foo lset list $n $temp \(except, of course that no _temp_ variable is created\) The usage: lset list end+1 0 foo or, equivalently, lset list end+1 end+1 foo is equivalent to lappend list [list foo] # Rationale Clearly, there are equivalent constructs to all of these usages. Nevertheless, it is convenient not to have to worry about whether a given index is in bounds, particularly when iterating through a vector or matrix. With the proposed change, many of the standard algorithms in linear algebra will just work, without either having to preinitialize a list to a given size or to have a test to determine whether to use **lappend** or **lset** to store a given element. # Alternatives Explicitly out of scope is the treatment of indices greater than or equal to _end\+2_. Setting non-contiguous elements would raise false expectations of sparse lists, **NULL** elements, and so on. # Copyright Copyright © 2008 by Kevin B. Kenny. This document may be distributed subject to the terms and conditions set forth in the Open Publication License, version 1.0 <http://www.opencontent.org/openpub/> . |
Name change from tip/332.tip to tip/332.md.
|
| < | < | | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | < > | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 332: Half-Close for Bidirectional Channels Author: Alexandre Ferrieux <[email protected]> State: Final Type: Project Vote: Done Created: 25-Sep-2008 Post-History: Keywords: Tcl,channel,close,socket,shutdown Obsoletes: 301 Tcl-Version: 8.6 ----- # Abstract This TIP proposes to extend the **close**/**chan close** commands to let them perform an unidirectional "half-close" on bidirectional channels. # Background Bidirectional channels \(sockets and command pipelines\) allow Tcl to make an efficient use of a "filter process", by exchanging data back and forth over an abstract "single" channel. However, this single channel abstraction comes with a too coarse-grained **close** primitive. Indeed, it closes both directions simultaneously, while it is often desirable to close "gracefully" the half-connection _to_ the filter process, leaving the return path open. The effect of such a half-close is that the filter receives a bona fide EOF alone, without a nearly simultaneous SIGPIPE on its write end if it happens to be writing at that time. Moreover, if the filter is itself comprised of a pipeline of processes, some of which doing buffered I/O, then this graceful EOF may be the only way of flushing the chain and receiving back precious data. This technique is supported by all modern OSes: for pipes there are actually two separate file descriptors/handles, and it suffices to close\(\) the write side; for sockets, a single fd is used, but a specific syscall, shutdown\(\), brings back the ability to half-close. Hence it is fairly natural for a universal "OS glove" like Tcl to expose this universal feature. # Proposed Change This TIP proposes to extend the **close** and twin brother **chan close** commands to take an optional extra "direction" argument, indicating a half-close on the substream going in that direction: > **close** _channel_ ?**read**\|**write**? When the extra direction argument \(which may be abbreviated\) is given, first the OS-level half-close is performed: this means a shutdown\(\) on a socket, and a close\(\) of one end of a pipe for a command pipeline. Then, the Tcl-level channel data structure is either kept or freed depending on whether the other direction is still open: set f [open |command r+] ... close $f w ;# $f still exists ... close $f r ;# now $f is gone Also, a single-argument **close** on an already half-closed bi-channel is defined to just "finish the job", which allows to write blind cleanup procedures easily: if {[catch { set f [open |command r+] ... close $f w ... } err]} { ... close $f ;# close what's left } In the case of a command pipeline, the child-reaping duty falls upon the shoulders of the last close or half-close, so that an error condition at this stage \(like "Child exited abnormally"\) doesn't leak system resources. Last, a half-close on an already closed half raises an error: set [open |command r+] close $f w close $f w ==> channel "file3" wasn't opened for writing And the same applies to wrong-sided unidirectional channels: set [open filename r] close $f w ==> channel "file3" wasn't opened for writing # Rationale The concept has gone full circle. From an initial half-close proposal very close to the current one, an ambitious **chan split** generalization was born in the surrounding enthusiasm, and specified in [[301]](301.md). Then, [[304]](304.md)'s **chan pipe** was accepted, which addressed most of the "splitting" demand \(asymmetric fconfigures on both ends of a command pipeline can be done by redirecting to a standalone pipe\). Moreover, in hindsight it appears that the implementation of [[301]](301.md) had very long-ranging effects on various channel implementations, which are more numerous today than before \(TLS, reflection API\). As a consequence, [[301]](301.md) is being withdrawn, and the current TIP goes back to its initial, lower profile: just provide the half-close. # C Interface Luckily, the polymorphic channel API in Tcl has been fitted with a half-close function for nearly 10 years \(!\): the Tcl\_ChannelType structure has had a _close2proc_ member since 1998 in order to avoid deadlocks when closing a command pipeline. As a consequence, the implementation of half-close can be done with a constant channel ABI, avoiding any compatibility issue for extensions. Still, the _close2proc_ member does not have public status. To promote symmetry between the script-level and public C APIs, this TIP proposes to add an entry in the main stub table with the following signature: > int **Tcl\_CloseEx**\(Tcl\_Interp \*_interp_, Tcl\_Channel _chan_, int _flags_\) The behavior being defined as mirrorring the script-level semantics described bove, where _flags_ is either 0 \(meaning bidirectional close\) or one of TCL\_CLOSE\_READ and TCL\_CLOSE\_WRITE \(meaning half-close\). # Reference Implementation See Patch 219159 <https://sourceforge.net/tracker/index.php?func=detail&aid=219159&group_id=10894&atid=310894> . After a discussion with Andreas Kupries, the plan is to half-close-enable only raw \(unstacked\) channels for the time being, raising an explicit error when trying a half-close on a non-bottom channel. This leaves time to carefully design the necessary API extension of the generic stacking and reflection layers, while preparing a fully compatible change \(error cases becoming valid\). On the channel-type-dependent side, only sockets and pipelines will be half-close-enabled for now: these are assumed to represent the most pressing demand. # Copyright This document has been placed in the public domain. |
Name change from tip/333.tip to tip/333.md.
|
| < | < | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 333: New Variable and Namespace Resolving Interface Author: Arnulf Wiedemann <[email protected]> State: Draft Type: Project Vote: Pending Created: 13-Oct-2008 Post-History: Keywords: Tcl,resolution Tcl-Version: 8.7 ----- # Abstract This is a TIP to allow easy command and variable resolving for itcl-ng, but is not restricted to itcl-ng. It should be possible for an application to drive the rules for command and variable lookup using the interface described below. This TIP should allow to get rid of namespace and interpreter resolvers for itcl-ng. # Rationale The current implementation for command and variable resolution using namespace and interpreter resolvers has a lot of problems for the Tcl core implementation. Second problem is the additonal performance penality for using the resolvers \(much more code is needed in the application\). The suggested interface allows to hide Tcl core details concerning handling of variables and commands from the outside. If the interface would be made public, it would be also possible to avoid use of tclInt.h in that area and to only use stubs interfaces, which means itcl-ng versions would be independent of Tcl versions. Other applications \(e.g. snit\) could also use this interface for fast lookup of variables and commands. # C-API Specification At the moment there is only a need for a C-API for the suggested functionality ## For Commands \(methods/procs\) > typedef int \(\***TclCheckClassProtectionProc**\)\(Tcl\_Interp \*_interp_, Tcl\_Namespace \*_nsPtr_, const char \*_varName_, ClientData _clientData_\); > typedef void \(\***Tcl\_ClassCommandDeleteProc**\)\(ClientData _clientData_\); > typedef void \(\***Tcl\_ObjectCommandDeleteProc**\)\(ClientData _clientData_\); > ClientData **Tcl\_RegisterClassMethod**\(Tcl\_Interp \*_interp_, Tcl\_Namespace \*_nsPtr_, const char \*_cmdName_, ClientData _clientData_\); > Tcl\_Command **Tcl\_RegisterObjectMethod**\(TclInterp \*_interp_, ClientData _objectPtr_, const char \*_cmdName_, Tcl\_Command _cmdPtr_, ClientData _clientData_\); > void **Tcl\_UnregisterClassCommand**\(Tcl\_Interp \*_interp_, Tcl\_Namespace *_nsPtr_, const char \*_cmdName_, Tcl\_ClassCommandDeleteProc _delProc_\); > void **Tcl\_UnregisterObjectCommand**\(Tcl\_Interp \*_interp_, ClientData _objectPtr_, const char \*_cmdName_, Tcl\_ObjectCommandDeleteProc _delProc_\); > int **Tcl\_SetCallFrameObject**\(Tcl\_Interp \*_interp_, ClientData _objectPtr_\); > int **Tcl\_SetNamespaceCommandProtectionCallback**\(Tcl\_Interp \*_interp_, Tcl\_Namespace \*_nsPtr_, TclCheckNamespaceProtection _cnpProc_\); ## For Variables \(variables/commons\) > typedef int \(\***TclCheckClassProtection**\)\(Tcl\_Interp \*_interp_, Tcl\_Namespace \*_nsPtr_, const char \*_varName_, ClientData _clientData_\); > typedef void \(\***Tcl\_ObjectVariableDeleteProc**\)\(ClientData _clientData_\); > typedef void \(\***Tcl\_ClassVariableDeleteProc**\)\(ClientData _clientData_\); > ClientData **Tcl\_RegisterClassVariable**\(Tcl\_Interp \*_interp_, Tcl\_Namespace \*_nsPtr_, const char \*_varName_, ClientData _clientData_\); > Tcl\_Var **Tcl\_RegisterObjectVariable**\(TclInterp \*_interp_, ClientData _objectPtr_, const char \*_varName_, ClientData _clientData_, Tcl\_Var _varPtr_\); > void **Tcl\_UnregisterClassVariable**\(Tcl\_Interp \*_interp_, Tcl\_Namespace \*_nsPtr_, const char \*_varName_, Tcl\_ClassVariableDeleteProc _delProc_\); > void **Tcl\_UnregisterObjectVariable**\(Tcl\_Interp \*_interp_, ClientData _objectPtr_, const char \*_varName_, Tcl\_ObjectVariableDeleteProc _delProc_\); > int **Tcl\_SetCallFrameObject**\(Tcl\_Interp \*_interp_, ClientData _objectPtr_\); > int **Tcl\_SetNamespaceVariableProtectionCallback**\(Tcl\_Interp *_interp_, Tcl\_Namespace \*_nsPtr_, TclCheckNamespaceProtection _cnpProc_\); # Detailed Description For details on how itcl-ng is using variables scopes and command scopes look here: <http://wiki.tcl.tk/21676> I am only describing details for variables, as variables are more complex and commands are handled very similar to variables in itcl-ng concerning lookup. There is the need for collecting all variables from an itcl-ng class hierarchy for every class in the hierarchy together with the class \(which is a namespace\). Then for each such collection there is the need to specify which variables are used phisically based on a per object basis, because every object has an own set of variables for the class hierarchy tied to the object. There is the need to switch these variable collections during runtime for every itcl-ng method \(a method is similar to a tcl proc\) which is called. Every method is called in the class \(namespace\) where it is defined. Therefor it is necessary to have a registration mechanism for variables on a class and object base. During execution when calling a method the appropriate set of object variables for the currently active object has to be available on a per CallFrame basis \(Tcl\_SetCallFrameObject\). The protection check function shall be called when a class variable is found to check the protection level by the caller according to the protection rules for the application. The clientData structure has to be filled by the application with the appropriate data when registering a variable. The suggested rules for lookup should be: on all places where the namespace resolvers are called at the moment to additionally \(instead of\) do the lookup for the new interfaces and if there is nothing found continue with normal lookup. The \*Unregister\* functions are for cleaning up variable information when no longer needed. The application has to do the calls and the deleteProc is used for freeing the contents of the clientData containers used when registering the variables. If no registered variable for a class or object is left, also the data structures in Tcl core used for registering and lookup should be freed. For commands substitute variable by command in the last few sections. The names for the interface functions are just a suggestion, maybe someone finds better names. # Reference Implementation A reference implementaion has been done for itcl-ng using the namespace resolvers and in the resolver functions using the described interfaces. It runs aganist the test suite without problems. # Details about the Reference Implementation I have used a straight forward approach, which was easy to implement. All lookup info is at the moment in a structure available with Tcl\_SetAssocData/Tcl\_GetAssocData Tcl\_RegisterClassVariable fills a Tcl\_HashTable with the namespace as the key \(not necessary in Tcl core there the info should be tied to the Namespace structure\). The value is a Tcl\_HashTable for the variable infos. In that hash table there are entries with varName as a key and clientData as the value. Tcl\_RegisterObjectVariable fills a Tcl\_HashTable with the objectClientData as key and value is a Tcl\_HashTable. The key for the hash table is clientData tied to a varName from Tcl\_RegisterClassVariable and if varPtr != NULL then it is the value for the hash table otherwise a new variable is created and used for the varPtr. The variable is created at the moment in a special per object namespace but better should be stored in a per object TclVarHashTable. Lookup in the namespace resolvers fetches the lookup data structure, looks with namespace and varName for clientData, and if found calls Tcl\_CheckClassProtection and if TCL\_OK is returned gets the itcl object and looks for the varPtr with objectClientData and clientData and if successful returns varPtr. # Copyright This document has been placed in the public domain. |
Name change from tip/334.tip to tip/334.md.
|
| < | < | | | | | | | | > | | | | | | | | | | | > | 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 | # TIP 334: Make 'lrepeat' Accept Zero as a Count Author: Michael Thomas Greer <[email protected]> State: Withdrawn Type: Project Tcl-Version: 8.6 Vote: Pending Created: 13-Oct-2008 Post-History: Keywords: empty list ----- # Abstract Following on from [[323]](323.md), the **lrepeat** command should also act gracefully when a repeat count of zero is used, as an empty list is still a valid list. # Rationale A list of zero items is a valid, empty list. In my own experience \(I cannot speak for others'\), generating a list of _N_ identical elements is more often an algorithmic expression than a literal shorthand, and often enough an empty list is the correct result. All other core list commands properly handle empty lists; but **lrepeat** complains when given a count of zero repetitions, requiring additional code to handle this \(doubly\) exceptional condition. # Proposal The **lrepeat** command should be changed so that when it's first, _count_, argument is zero, it returns an empty list. # Copyright This document has been placed in the public domain. |
Name change from tip/335.tip to tip/335.md.
|
| < | < | | | | | | | | > | | | | | | | | | | | | | | < > | < > | < > | | < > | | < > | | | | | < > | < | > | > | 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 | # TIP 335: An API for Detecting Active Interpreters Author: Joe Mistachkin <[email protected]> State: Final Type: Project Vote: Done Created: 13-Oct-2008 Keywords: numLevels,embedding,terminate,async,thread,safe,gc Tcl-Version: 8.6 Post-History: ----- # Abstract This TIP introduces the ability to quickly and safely decide whether a Tcl script is evaluating in an interpreter, allowing an external system to determine whether it is safe to delete that interpreter. # Rationale For applications written in garbage-collected languages, such as C\#, it is not always desirable to rely upon the **Tcl\_Preserve** / **Tcl\_Release** mechanism to protect an against deletion of an interpreter while it is in use. For details of how this is used, see <http://wiki.tcl.tk/6580> <http://eagle.to/> and Joe Mistachkin's talk at Tcl 2008. Additionally, an application may want to proactively forbid attempts to delete an interpreter while it is in use. Unfortunately, there is currently no publicly exposed method to determine if a given Tcl interpreter is in use \(i.e. one or more calls to **Tcl\_Eval** are active\). This TIP proposes to correct that deficiency. # Specification This TIP introduces a single function to Tcl's public API: > int **Tcl\_InterpActive**\(Tcl\_Interp \*_interp_\) The **Tcl\_InterpActive** function returns non-zero if the interpreter is in use, and zero if it is idle \(i.e. not evaluating any script\). # Reference Implementation /* *---------------------------------------------------------------------- * * Tcl_InterpActive -- * * Returns non-zero if the specified interpreter is in use. * * Results: * See above. * * Side effects: * None. * *---------------------------------------------------------------------- */ int Tcl_InterpActive(Tcl_Interp *interp) { return (((Interp *) interp)->numLevels > 0); } # Copyright This document has been placed in the public domain. |
Name change from tip/336.tip to tip/336.md.
|
| < | < | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | < > | | | < | > | | | | | | | | | | > | 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 | # TIP 336: Supported Access To interp->errorline Author: Don Porter <[email protected]> State: Final Type: Project Vote: Done Created: 21-Oct-2008 Post-History: Tcl-Version: 8.6 ----- # Abstract This TIP proposes a supported public interface to set and get the value of the _errorLine_ field of the _Tcl\_Interp_ data structure. # Background A more forceful barrier to direct access to the _result_ and _freeProc_ fields of the _Tcl\_Interp_ data structure has just been accepted [[330]](330.md). This revision leaves only the _errorLine_ field still normally publicly visible. The visibility of this field prevents the realization of _Tcl\_Interp_ as a fully opaque data structure. The _result_ and _freeProc_ fields have long had the recommended alternatives of **Tcl\_GetStringResult** and **Tcl\_SetResult** which make direct access unnecessary. The _errorLine_ field has long gone without such alternatives. Starting with Tcl 8.5, some alternatives do exist. The value of the _errorLine_ field can be set by passing an appropriate dictionary to **Tcl\_SetReturnOptions** and the value can be retrieved from the dictionary returned by passing **TCL\_ERROR** to **Tcl\_GetReturnOption** [[227]](227.md). The housekeeping burden of these alternatives is significant, so there's little attraction for replacing direct access to the _errorLine_ field with them. Specialized routines already exist for managing the fully private fields _errorInfo_ and _errorCode_ in the opaque part of the _Interp_ data structure, **Tcl\_SetErrorCode**, **Tcl\_AddErrorInfo**, etc. The management of these values is needed frequently enough to make simplified alternatives like this worthwhile. # Proposal Create the following new public routines to get and set the _errorLine_ field: > int **Tcl\_GetErrorLine**\(Tcl\_Interp \*_interp_\) > void **Tcl\_SetErrorLine**\(Tcl\_Interp \*_interp_, int _value_\) These will be implemented as \(equivalent to\): int Tcl_GetErrorLine(Tcl_Interp *interp) { return ((Interp *) interp)->errorLine; } void Tcl_SetErrorLine(Tcl_Interp *interp, int value) { ((Interp *) interp)->errorLine = value; } In addition, following the example of [[330]](330.md), disable the default public access to the _errorLine_ field, permitting the restoration of access only when the **USE\_INTERP\_ERRORLINE** directive is defined. # Compatibility This change is a source incompatibility with C code directly accessing the _errorLine_ field. The quick fix to restore compatibility is to define **USE\_INTERP\_ERRORLINE**. The next step for migrating old code would be to adopt the new routines, and offer macros to duplicate the effect of the new routines when older Tcl headers are in use. # Rationale This is the last stepping stone to prepare the way for _Tcl\_Interp_ to become a fully opaque data structure. The rationale for the immediate disabling of public access is to \(over?\)learn the lesson of [[330]](330.md). No matter how sternly you warn about deprecation, nothing happens until you turn it off, so let's move immediately to turning it off, with the burden on the users to restore what they need. # Copyright This document has been placed in the public domain. |
Name change from tip/337.tip to tip/337.md.
|
| < | < | | | | | | | > | | | | | | | | | | | | | < | > | | | | | | | | | | | > | 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 | # TIP 337: Make TclBackgroundException() Public Author: Don Porter <[email protected]> State: Final Type: Project Vote: Done Created: 21-Oct-2008 Post-History: Tcl-Version: 8.6 ----- # Abstract This TIP proposes to make the _TclBackgroundException_ routine available in the public interface so that extensions may notify Tcl about all return codes that occur during background operations. # Background When background operations in Tcl result in a non-**TCL\_OK** return code, it has been recommended practice to call _Tcl\_BackgroundError\(\)_ so that Tcl can arrange for background error handlers to react to the exceptional situation. The prototype of that routine is: > void **Tcl\_BackgroundError**\(Tcl\_Interp \*_interp_\) In Tcl 8.5, the new **interp bgerror** command permits registration of handlers that receive the full return options dictionary as an argument [[221]](221.md). This means that such handlers can respond differently to different exceptions. At the same time a new internal routine **TclBackgroundException** with prototype: > void **TclBackgroundException**\(Tcl\_Interp \*_interp_, int _code_\) and the implementation of **Tcl\_BackgroundError** became: void Tcl_BackgroundError(Tcl_Interp *interp) { TclBackgroundException(interp, TCL_ERROR); } The new **TclBackgroundException** routine is a more general routine suitable for announcing any exceptional code returned by background operations, not limited to **TCL\_ERROR** like **Tcl\_BackgroundError** has been. The new **TclBackgroundException** routine is used throughout the internal portions of Tcl so that full exception information gets reliably passed through to background exception handlers, when the background processing is governed by things which are built in to Tcl, such as **after** and **chan event**. The oversight of [[221]](221.md) was not proposing to make **TclBackgroundException** public at the same time, so that extensions which govern background operations, notably Tk, have access to the same full expressive power. # Proposal Rename the internal routine **TclBackgroundException** to **Tcl\_BackgroundException** and place it in the public stubs table. Apply Tk Patch 1789752 <https://sourceforge.net/support/tracker.php?aid=1789752> to make use of the new facility. # Compatibility No compatibility concerns from a new public routine. # Copyright This document has been placed in the public domain. |
Name change from tip/338.tip to tip/338.md.
|
| < | < | | | | | | | | > | | | | | | | | | | | | | | > | 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 | # TIP 338: Embedder Access to Startup Scripts of *_Main() Author: Don Porter <[email protected]> State: Final Type: Project Vote: Done Created: 22-Oct-2008 Post-History: Tcl-Version: 8.6 Keywords: Tcl, Tk, tclsh, wish ----- # Abstract This TIP proposes to make public the routines that get and set the startup script file that _Tcl\_Main_ or _Tk\_Main_ evaluate in their non-interactive modes. # Background When support for the **-encoding** option was added to tclsh and wish [[137]](137.md), two new internal routines were added to Tcl: > Tcl\_Obj \***Tcl\_GetStartupScript**\(const char \*\*_encodingNamePtr_\) > void **Tcl\_SetStartupScript**\(Tcl\_Obj \*_pathPtr_, const char *_encodingName_\) These routines \(or other weaker alternative internal routines\) are used by both wish and Tclkit by way of the internal stubs table to manipulate the startup script for _Tcl\_Main_ or _Tk\_Main_ to evaluate. # Rationale The naming of these routines indicate they were always intended to be\(come\) public. These are the last "private" Tcl routines used by Tk and wish. After implementation of this TIP, Tk can drop use of tclInt.h. # Proposal Make these routines public. # Compatibility There will need to be some care taken for existing users of these routines via the private stubs table. The ability to compile against Tcl 8.6 headers, yet run against a pre-8.6 stubs table will likely be lost. # Copyright This document has been placed in the public domain. |
Name change from tip/339.tip to tip/339.md.
|
| < | < | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 339: Case-Insensitive Package Names Author: Andreas Kupries <[email protected]> State: Rejected Type: Project Vote: Done Created: 14-Nov-2008 Post-History: Tcl-Version: 8.6 ----- # Abstract This document proposes to change the package management facilities of the Tcl core to handle package names in a case-insensitive manner, switching back to case-sensitive operation if and only if explicitly requested by the user. The case of package names is preserved in the storage however. # Rationale The package management facilities of Tcl are an area where the user of packages is currently burdened with more ... than is convenient or easy. A big problem is that Tcl compares package names case-sensitively. This means that _Expect_ and _expect_ are two different things to Tcl. In the real world however having two packages using the same name but different capitalization is extremely rare. Yet the user of Tcl package facilities has to remember whatever ecclectic capitalization the package creator has chosen. Changing this, i.e. having Tcl's package management go to case-insensitive comparison, will lift this burden and make things easier, as it is not necessary anymore to get the capitalization right. Most people will likely simply start to write all package names lower-case after this change. # Specification ## Script Level The only command affected by the proposed change is **package**. More specifically, its sub-commands _ifneeded_, _present_, _require_, and _versions_. In detail * **package require** _name_ ... > This sub-command is changed to accept an additional option _-strict_. > If this option is present the sub-command performs an old-style, i.e. case-sensitive search for the package _name_. > Otherwise the command is changed to disregard case during the search for _name_. In that case it is possible that multiple packages are found which have the same name, just with different capitalizations. To resolve this conflict the command will load the package in the matching set which was added first to its memory database via **package ifneeded**. > If that resolves to the wrong package the user has to use _-strict_ and specify the exact name of the package required, capitalization and all. Given our rationale for the TIP this should be required seldomly. * **package present** ?-exact? _name_ ?_version_? > This sub-command is changed to accept an additional option _-strict_. > If this option is present the sub-command performs an old-style, i.e. case-sensitive search for the package _name_. > Otherwise the command is changed to disregard case during the search for _name_. In that case it is possible that multiple packages are found which have the same name, just with different capitalizations. To resolve this conflict the command will return the version of the package in the matching set it found first among the loaded packages. > If that resolves to the wrong package the user has to use _-strict_ and specify the exact name of the package to look for, capitalization and all. Given our rationale for the TIP this should be required seldomly. * **package versions** _name_ > This sub-command is changed to accept an additional option _-strict_. > If this option is present the sub-command performs an old-style, i.e. case-sensitive search for the package _name_. > Otherwise the command is changed to disregard case during the search for _name_. In that case it is possible that multiple packages are found which have the same name, just with different capitalizations. To resolve this conflict the command will return the version of the package in the matching set which was added first to its memory database via **package ifneeded**. > If that resolves to the wrong package the user has to use _-strict_ and specify the exact name of the package to query, capitalization and all. Given our rationale for the TIP this should be required seldomly. * **package forget** _name_ ... > This sub-command is changed to accept an additional option _-strict_. > If this option is present the sub-command performs an old-style, i.e. case-sensitive search for the package _name_ to forget. > Otherwise the command is changed to disregard case during the search for _name_. In that case it is possible that multiple packages are found which have the same name, just with different capitalizations. Instead of resolving the conflict by forgetting only the first package found among the loaded this command will forget **all** of the packages matching the name. > If that does more than intended the user has to use _-strict_ and specify the exact name\(s\) of the package to forget, capitalization and all. Given our rationale for the TIP this should be required seldomly. * **package provide** _name_ _version_ > This form of the command is left unchanged. * **package provide** _name_ > This form of the command is like **package present**, except for the different handling of a package not in memory. It is therefore changed in the same manner, i.e: > This form of the sub-command is changed to accept an additional option _-strict_. > If this option is present this form of the sub-command performs an old-style, i.e. case-sensitive search for the package _name_ before returning its version, or the empty string if nothing was found. > Otherwise this form of the sub-command is changed to disregard case during the search for _name_. In that case it is possible that multiple packages are found which have the same name, just with different capitalizations. To resolve this conflict the command will return the version of the package in the matching set it found first among the loaded packages. > If that resolves to the wrong package the user has to use _-strict_ and specify the exact name of the package to look for, capitalization and all. Given our rationale for the TIP this should be required seldomly. * **package ifneeded** _name_ _version_ _script_ > This form of the command is left unchanged. It keeps storing the package name as given, preserving capitalization, and _package provide_ searches case-sensitively. This means that the name used by **provide** has to match the name used by the **ifneeded**, just like the version numbers have to match. While we are working on easing the load on the user of a package with regard to letter case we do assume that the developer of a package does know how it is spelled, capitalization and all, therefore a strict, case-sensitive search is best to detect such avoidable mismatches. * **package ifneeded** _name_ _version_ > This form of the command is similar to **package present** or **package provide**. It is therefore changed in the same manner, i.e: > This form of the sub-command is changed to accept an additional option _-strict_. > If this option is present this form of the sub-command performs an old-style, i.e. case-sensitive search for the package _name_ before returning the script, or the empty string if nothing was found. > Otherwise this form of the sub-command is changed to disregard case during the search for _name_. In that case it is possible that multiple packages are found which have the same name, just with different capitalizations, and the same version. To resolve this conflict the command will return the script of the package in the matching set it found first among the loaded packages. > If that resolves to the wrong package the user has to use _-strict_ and specify the exact name of the package to look for, capitalization and all. Given our rationale for the TIP this should be required seldomly. ## C API At the C-level the only functions to consider are * Tcl\_PkgPresent * Tcl\_PkgPresentEx * Tcl\_PkgRequire * Tcl\_PkgRequireEx * Tcl\_PkgRequireProc The first four of these currently have an integer \(boolean\) argument _exact_. This argument is changed to an integer \(bitset\) _flags_, with the original exact value residing in bit 0. The strictness of the package name comparison is encoded in bit 1. For easy access to the flags we define #define TCL_PKG_EXACT 1 /* Exact version required */ #define TCL_PKG_STRICT 2 /* Use strict (case-sensitive) package name * comparison */ This change relies on the assumption that all \(most\) existing users of these functions use the constants 0 and 1 for _exact_, making them fully backward compatible. The last function, _Tcl\_PkgRequireProc_, has no arguments we can modify in this manner. Its behaviour is changed to perform case-insensitive searches, as specified above for the associated subcommands of **package**, and a new function is added for access to the old behaviour, i.e. case-sensitive searches. This new function is * Tcl\_PkgRequireProcEx It has the same signature as its pre-TIP counterpart, except that a _flags_ argument is added after the clientData. This argument recognizes _TCL\_PKG\_STRICT_ as defined above and uses it to switch between case-insensitive and strict search. The old _Tcl\_PkgRequireProc_ is reimplemented in terms of _Tcl\_PkgRequireProcEx_. ## Unknown handlers The contract between the package management facilities in the Tcl core and the handler commands registered with _package unknown_ is amended. The handler has to perform case-insensitive search for the package whose name it is invoked with. ## Discussions The contract for the package unknown handler is amended because not doing so would force the package management facilities in the Tcl core to search for a package by iterating over all possible combinations of upper/lower case in the package name. For a name containing N alphabetic characters \(i.e. not counting ':'s, and digits\) this means to loop 2\*\*N times. This exponentional explosion and consequent running time is not acceptable \(The longest name for a package currently found in ActiveState's public TEApot repository is 25 alpabetic characters, forcing over 30 million searches before the core can give up\). Further, of the two known standard package unknown handlers the handler for regular packages need not be modified at all as it always register every possible package it finds. Only the unknown handler for Tcl Modules has to be modified to perform case insensitive filesystem searches, and only for Unix. On Windows the builtin **glob** command already perform such. # Reference Implementation An implementation patch is available at SourceForge <http://sourceforge.net/support/tracker.php?aid=2316115> . # Copyright This document has been placed in the public domain. Please note that any correspondence to the author concerning this TIP is considered in the public domain unless otherwise specifically requested by the individual\(s\) authoring said correspondence. This is to allow information about the TIP to be placed in a public forum for discussion. |
Name change from tip/34.tip to tip/34.md.
|
| < | < | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 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 | # TIP 34: Modernize TEA Build System Author: Mo DeJong <[email protected]> Author: Andreas Kupries <[email protected]> State: Withdrawn Type: Project Vote: Done Created: 03-May-2001 Post-History: Tcl-Version: 8.5 ----- # Abstract A number of things in the original TEA specification and documentation have fallen out of date. Numerous complaints about the difficulty of creating a TEA compliant package have appeared on news:comp.lang.tcl. Other complaints about the ease of building Tcl and Tk using the autoconf based build system have also surfaced. Addressing these concerns is made even more difficult by the fact that two independent build systems currently exist, one for UNIX, and one for Windows. Maintaining multiple build systems is a frustratingly slow process that wastes time better spent on other issues. In addition, the Tcl build scripts do not support cross compilation which makes the maintenance process even slower since one can't test simple build system changes for a given platform without access to that platform. This document describes how these concerns can be addressed. # Documentation As new software is released, existing documentation becomes obsolete. Some of the existing TEA documentation is now so badly out of date that suggested software releases are no longer available. For example, the TEA based build for Windows requires Cygwin, yet there is a lack of clear instructions that describe how to install Cygwin. The solution to this problem is simple, the TEA documentation and implementation must be updated. # Platform Detection Most open source packages make use of a pair of scripts called _config.guess_ and _config.sub_ to detect a platform specific configuration string. For example, running _config.guess_ on an x86 Linux box might print: % ./config.guess i686-pc-linux-gnu This value can be accessed from the configure.in script by adding a call to the _AC\_CANONICAL\_HOST\(\)_ macro. One would then detect a specific platform by doing a switch on the value of the $host variable. Tcl currently detects the build platform by examining the results of running _\`uname -s\`-\`uname -r\`_. Tcl should use the _config.guess_ and _config.sub_ method of platform detection. This may not seem like a big change at first but it has quite a few ramifications. This change cannot be made incrementally, so there is a real danger of breaking the build for configurations that currently work. For this reason, it would be a good idea to wait until a 8.4 release branch has been created before adding such a change to the CVS HEAD. The cross compiling section will describe some of the other maintenance benefits that can be realized by using _config.sub_ and _config.guess_. # Cross Compiling Tcl's build system has never supported cross compiling. The use of uname instead of _config.guess_ during platform detection is largely to blame for this. A configure script that makes use of the _AC\_CANONICAL\_HOST\(\)_ macro keeps track of two separate configuration variables, _build_ and _host_. The _build_ variable holds the configuration string for the platform running the _./configure_ script. The _host_ variable holds the configuration string for the platform the generated binaries will be run on. For example, if one were to build a Windows binary under Linux the _build_ variable could be set to _i686-pc-linux-gnu_ and the _host_ variable could be set to _i386-pc-mingw32msvc_. Using the host variable instead of the output of _uname_ has another important benefit. The build system maintainer can often test out changes to the build system logic without having access to the system in question. This is important since a surprising number of "broken builds" are the result of stupid logic or syntax errors in the sh code for a particular platform. For example, one could test out the Windows build using a cross compiler prefixed by _i386-mingw32msvc_ like so: % ./configure --host=i386-mingw32msvc % make The above commands will run the Windows configure script in bash and then generate Win32 .dll and .exe files. One can even create cross compilers for multiple systems. Binaries for Solaris, IRIX, or others can be created under Linux or even Windows. The attentive reader will note that even compiling a Win32 application under Cygwin is technically a cross compile since the generated executable would be run with the Win32 runtime instead of the Cygwin runtime. To properly support cross compiling and make it easy for the end user, an upgrade to autoconf is also required. # Autoconf 2.50 Update The autoconf 2.13 release is now several years old. The most recent stable release of autoconf is 2.50. A huge number of problems have been fixed in the autoconf 2.50 release, the most important of which is cross compiling support. Cross compiling with autoconf 2.13 is possible but far harder than it needs to be. The long and sordid history of this particular feature in autoconf will not be addressed in this document. It is safe to say that the autoconf 2.50 release is the first release to make cross compiling easy for the end user. The existing build system works with the autoconf 2.50 release on a number of systems, but it is possible that the build on some system would be broken by this upgrade. For this reason, the autoconf 2.50 upgrade should happen after an 8.4 branch has been created. # Use a Config Header Autoconf supports two ways to set platform specific flags set via the _AC\_DEFINE\(\)_ macro. Tcl currently makes use of the default option. Each call to _AC\_DEFINE\(\)_ adds a _-DVAR=1_ value that is passed into the compiler. These _-D_ flags are also included in the generated _tclConfig.sh_ file so that extensions will use the same set of defines. The second option is to generate a .h file that will be \#included into any needed header or source file. This file could be called _tclconfig.h_. Instead of passing _-DVAR=1_ on the command line, the generated .h file might look like: # define VAR 1 There is no functional difference between these two options. The benefit of using _tclconfig.h_ will likely only be realized by the maintainers or people hacking on the core and extensions. By taking the -D flags out of the _Makefile_, we make it easier to hack around in the generated .h file without having to worry about also changing the flags in the generated _tclConfig.sh_ file. It can be quite a pain to change an option in Tcl's _Makefile_, then again in the _tclConfig.sh_ file, and then rerun the configure script in each extension. This pain can be avoided by adding a call to _AM\_CONFIG\_HEADER\(tclconfig.h\)_ to the top of Tcl's _configure.in_ script. One possible ramification of this change may be the need to install _tclconfig.h_ in the event items in _tclInt.h_ depend on \#defines in _tclconfig.h_. # Misplaced AC\_SUBST Calls The _configure.in_ file for both Tcl and Tk invokes the _AC\_SUBST\(\)_ macro for each variable that is to be substituted into the _Makefile_. This makes sense for variables defined in the _configure.in_ file, but it makes no sense for those variables defined in _tcl.m4_. Invoking _AC\_SUBST\(\)_ in _configure.in_ for a variable defined in _tcl.m4_ means that the maintainer will need to keep track of the variable in Tcl's _configure.in_ as well as the _configure.in_ of any extension that uses the given variable. This simply makes no sense. Each macro defined in _tcl.m4_ should call _AC\_SUBST\(\)_ for any variables it wishes to substitute into generated files. # One Rule to Build Them All Perhaps the most frustrating thing about maintaining Tcl's build system is the fact that each and every modification needs to be made and tested in at least 4 configurations. This is because Tcl and Tk have two separate build systems, one for Unix and one for Windows. Each and every change needs to be tested on Unix for both Tcl and Tk and then again on Windows for both Tcl and Tk. It is an incredible waste of time. A single build system with properly abstracted macros can be used to build both a Unix and Windows version of Tcl. Changes would still need to be tested on each platform, but dealing with only one source base would save a significant amount of the maintainer's time. A related problem is experienced by extension authors. It can be quite difficult to write a build system for an extension that works with both the Unix and Windows version of Tcl. Here is a telling quote from Todd Helfter, the maintainer of the Oratcl extension. > _"TEA specifies that there should be only one set of configure files. Why should extension writers have to comply with a standard that Tcl nor Tk does not?"_ For starters, some of the variables defined in the Unix version of _tclConfig.sh_ do not exist in the Windows version. Most of the obvious problems in this area have already been corrected in the 8.4 release, but some difficult ones remain. For example, how would an extension author figure out how to name a generated library file in a cross platform way? One would assume that a couple of variables could be concatenated together, but in practice this is not so easy. A quick look at the _configure.in_ scripts will turn up examples like this: \(Unix version\) if test "${SHARED_BUILD}" = "1" ; then eval "TCL_LIB_FILE=libtcl${TCL_SHARED_LIB_SUFFIX}" else eval "TCL_LIB_FILE=libtcl${TCL_UNSHARED_LIB_SUFFIX}" fi \(Windows version\) eval "TCL_LIB_FILE=${LIBPREFIX}tcl$VER${LIBSUFFIX}" The attentive reader will note that these are completely different! To understand the Unix version, one has to go exploring to find out how _TCL\_[UN]SHARED\_LIB\_SUFFIX_ gets set. To understand the Windows version, one needs to look into the origins of _LIBPREFIX_ and _LIBSUFFIX_. It is really quite a bother and it gets even worse once you introduce additional compilers \(like mingw\) into the mix. The casual coder would poke around for a bit then give up. The solution to this problem is to merge the two build systems and provide some properly abstracted macros that work on multiple platforms. These macros will need to be available to Tcl/Tk as well as extension authors. Here is a short example of a couple of macros that were developed while porting Tcl/Tk and Itcl to the Cygnus environment. These macros can be found in the current CVS HEAD of gdb/Insight. TCL_TOOL_STATIC_LIB_LONGNAME(VAR, LIBNAME, SUFFIX) TCL_TOOL_SHARED_LIB_LONGNAME(VAR, LIBNAME, SUFFIX) Using these macros, one could code the Unix and Windows versions to use the same logic. if test "${SHARED_BUILD}" = "1" ; then TCL_TOOL_SHARED_LIB_LONGNAME(TCL_LIB_FILE, tcl, ${TCL_SHARED_LIB_SUFFIX}) else TCL_TOOL_STATIC_LIB_LONGNAME(TCL_LIB_FILE, tcl, ${TCL_UNSHARED_LIB_SUFFIX}) fi Behind the scenes, the unix version might set _TCL\_LIB\_FILE=libtcl83.so_ while the Windows version might set _TCL\_LIB\_FILE=tcl83.dll_. Once both build systems use the same code, we can abstract them out into a new _tcl.m4_ file that is shared between the Unix and Windows versions. An extension that has only one build system can also make use of these macros. The concept is not a difficult one, the problem is that the implementation takes a very long time to get right. # VC\+\+ vs. GCC Library Names The previous section touched on issues related to library naming and how they differ between Unix and Windows. This section will focus only on Windows and discuss some of the differences that make it difficult to support both the VC\+\+ and gcc compilers. Two variables that are quite difficult to support properly are _TCL\_LIB\_SPEC_ and _TCL\_BUILD\_LIB\_SPEC_. The gcc compiler supports command line arguments like _-L$\{dir\} -l$\{lib\}_ but VC\+\+ does not. VC\+\+ users must pass the fully qualified name of a .lib file or set an environment variable. To deal with this situation, the following macros were developed. TCL_TOOL_LIB_SHORTNAME(VAR, LIBNAME, VERSION) TCL_TOOL_LIB_SPEC(VAR, DIR, LIBARG) A single _configure.in_ file for Tcl or an extension could make use of these macros as follows: TCL_TOOL_LIB_SHORTNAME(TCL_LIB_FLAG, tcl, ${TCL_VERSION}) TCL_TOOL_LIB_SPEC(TCL_BUILD_LIB_SPEC, `pwd`, ${TCL_LIB_FLAG}) TCL_TOOL_LIB_SPEC(TCL_LIB_SPEC, ${exec_prefix}/lib, ${TCL_LIB_FLAG}) When configured with VC\+\+, the macros would set: TCL_BUILD_LIB_SPEC="/build/tcl83.lib" TCL_LIB_SPEC="/install/tcl83.lib" When configured with gcc, the macros would set: TCL_BUILD_LIB_SPEC="-L/build -ltcl83" TCL_LIB_SPEC="-L/install -ltcl83" These macros are a good first step. They provide abstraction for library naming issues and work in both shared and static builds. This set of macros has been tested with Tcl, Tk, and Itcl and should be ready for incorporation into other extensions. One only needs to look at Tcl bug 219330 to find an example of a core extension that only builds with VC\+\+ under Windows. An extension writer should not need to solve compiler problems such as this. The Tcl core needs to provide abstracted macros that can be used in extensions. # Cygwin vs. Mingw The Windows version of Tcl traditionally supported building with VC\+\+ only. During the Tcl 8.3 development process, gcc support was added. Trouble is, the default version of gcc delivered with Cygwin had and continues to have some problems compiling the Windows Tcl code. Cygwin is a Unix/POSIX compatibility layer built on top of the Win32 API. The Cygwin version of gcc is designed to help people compile C programs that make use of POSIX APIs. The Cygwin version of gcc was not designed to support compiling Win32 native applications. Some support for Win32 applications was added later via the _-mno-cygwin_ command line switch, but it is far from perfect. The Mingw project was created to produce a version of gcc that supports building native Win32 applications. This version of gcc is a native Windows application, it does not depend on the Cygwin dll and it does not link generated applications to the Cygwin dll. In fact, it is simply not possible to create an executable that accidently requires the Cygwin dll when compiling with the Mingw version of gcc. This can be a problem with the Cygwin version of gcc, especially when C\+\+ is involved. Tcl currently builds with the Mingw version of gcc. Tcl does not build with the Cygwin version of gcc even though the _-mno-cygwin_ is used. Tcl also does not build using the Cygwin version of gcc in POSIX mode without the _-mno-cygwin_ flag. In addition, the individual working on Cygwin compatibility for Tcl will not be pursuing it in the future. For all of these reasons, support for Cygwin gcc should be dropped in favor of Mingw gcc. Documentation should be updated to instruct people to install the Mingw version of gcc instead of the Cygwin version. It is even possible to have both Cygwin gcc and Mingw gcc installed on the same system, the user just needs to make sure the correct one is on the PATH before compiling Tcl. A check should also be placed in the configure.in script to keep people from accidently compiling with the Cygwin version of gcc since it does not work and will only lead to useless bug reports. # A New tclconfig Module A number of Tcl extensions copy Tcl's _tcl.m4_ file into the extension's CVS module. For example, Itcl distributes a locally modified version of _tcl.m4_ that supports building on Windows and Unix with a single _configure.in_ script. It is very difficult to keep up maintenance when this sort of approach is used. For one thing, the maintainer has to constantly copy the _tcl.m4_ into extensions. Each and every commit to a _tcl.m4_ file in the _tcl_ CVS module needs to be followed by a commit to the same file in the _tk_ module. If an extension has made local modifications to the _tcl.m4_ file, a new one can't just me copied over. The extension maintainer would need to merge the changes in my hand or make use of some fancy CVS maintainer branch features that are not commonly used. The result of all this trouble is a predictable lag in keeping an extension's build system up to date. Perhaps the best solution to this problem is to create a new module in the Tcl CVS named _tclconfig_. This module would contain all the macro files and supporting scripts that were available to Tcl and any extensions. Anyone who has worked on tclpro will notice that this is equivalent to the _config_ module that currently exists in the _tclpro_ CVS. The idea is the same, but the new module needs to live in the _tcl_ CVS repo not the _tclpro_ CVS repo. When a user checks the _tcl_ module out of the CVS a _tclconfig_ directory will also be created. The _tcl/unix/aclocal.m4_ script would then be changed from: builtin(include,tcl.m4) To: builtin(include,../../tclconfig/tcl.m4) This approach will provide a single destination for all configure related changes. It will end the need to copy _tcl.m4_ files into each extension and will help extension authors resist the urge to make local modifications to the _tcl.m4_ script. If an extension author wants to change _tcl.m4_ they will need to submit a patch via the normal channels. Nothing will force extension authors to use this new approach, but it will be available to them when they are ready to upgrade. This change should not be integrated until Tcl 8.5. # Extension Defaults A Tcl extension should default to the same configuration options that Tcl was compiled with. For example, if _--prefix=/usr/local/tcl84_ is passed to Tcl's configure script, it should not also need to be passed to Tk's configure script [Tcl bug 428627]. Tk should use the compiler that Tcl was configured with by default. In fact, each of the following options could fit into this category: * --prefix * --exec-prefix * --host * --enable-threads * --enable-64bit * --enable-symbols * --enable-shared Each one of these options will need to be saved in _tclConfig.sh_. # Build vs. Install Configuration The _tclConfig.sh_ script should provide information that allows an extension to be built with either an installed or uninstalled version of Tcl. The current _tclConfig.sh_ largely fails to provide this functionality to extensions. Both build variables and install variables are included in the _tclConfig.sh_ file, but there is nothing to indicate to the script that loads _tclConfig.sh_ whether or not a given _tclConfig.sh_ has actually been installed. An extension author has a couple of choices about how to deal with this situation. One could simply recreate needed flags like _TCL\_LIB\_SPEC_ and _TCL\_STUB\_LIB\_SPEC_ and ignore the definitions in the _tclConfig.sh_ file. Tk uses this approach. One could also just pick from the build or install variables. If the extension author chose to use _TCL\_LIB\_SPEC_ instead of _TCL\_BUILD\_LIB\_SPEC_ then the extension would only build with a version of Tcl that was already installed. Itcl uses this approach. Both of these approaches are seriously flawed. Tcl needs to provide a means to load a _tclConfig.sh_ file without having to worry about build vs. install flags. The _SC\_LOAD\_TCLCONFIG_ macro can be modified in such a way as to define _TCL\_LIB\_SPEC=$TCL\_BUILD\_LIB\_SPEC_ when loading _tclConfig.sh_ from the build directory. When _tclConfig.sh_ is loaded from the install directory one could safely set _TCL\_BUILD\_LIB\_SPEC=$TCL\_LIB\_SPEC_. The above change would address the most obvious problem in _tclConfig.sh_, but others remain. Tcl bugs 219260 and 421835 provide some examples of variables in _tclConfig.sh_ that may work at build time but not install time and vice versa. One possible long term solution could be to create a _tclBuildConfig.sh_ as well as a _tclConfig.sh_ script. The _tclBuildConfig.sh_ could be loaded by the _SC\_LOAD\_TCLCONFIG_ macro when _--with-tcl_ indicated a build directory. The _tclConfig.sh_ script would not contain any build variables and would be the only configuration file to get installed. # Chicken or the Egg A number of targets in the current Tcl build process depend on having a working version of Tcl on the users _PATH_. It is not entirely clear if this was intentional. Either way, it creates real problems for users. Tcl bugs 420501 and 464874 demonstrates how a user might get a build error indicating that tclsh cannot be found before tclsh is even built. This problem should be straightforward to fix. Tcl patch 465874 describes on possible approach. The fact that this problem exists in the first place is indicative of a larger issue. The Tcl build process should minimize external dependencies. This seems like a simple thing to seek agreement on, but people are constantly advocating changes that fly in the face of this goal. Tcl bug 219259 describes one such misguided effort. Older releases of Itcl mistakenly assumed a version of tclsh would exist on the system and tried to install files using a Tcl script named _installFile.tcl_. [[59]](59.md) seeks to embed Tcl build information into tclsh so that Tcl extensions could build themselves using Tcl scripts. Each of these approaches make different assumptions about how Tcl will bootstrap itself. The current bootstrap approach depends on tclsh in some circumstances and not in others. This tends to work most of the time. Trouble is, if the user does something to change the time-stamps of certain files, |
︙ | ︙ | |||
461 462 463 464 465 466 467 | the generated version of tclsh would need to run on the host system. If the normal build process is always going to depend on tclsh, a private build version of tclsh will need to be bootstrapped. Realistically, this may be too much work to implement. It seems the only workable approach is to make sure none of the targets in the normal build process depend on an external tclsh. | | | | | | | | | | | | | | | | | | | > | 460 461 462 463 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 524 525 526 527 528 529 530 531 | the generated version of tclsh would need to run on the host system. If the normal build process is always going to depend on tclsh, a private build version of tclsh will need to be bootstrapped. Realistically, this may be too much work to implement. It seems the only workable approach is to make sure none of the targets in the normal build process depend on an external tclsh. # Death to TCL\_DBGX The most thoroughly evil part of the entire Tcl build process is the _TCL\_DBGX_ variable used in _configure.in_, _Makefile.in_, and _tclConfig.sh_. The following quote from Brent Welch say it all: > _"The TCL\_DBGX manifestation is one of the worst /bin/sh quoting hell situations I have encountered."_ Presumably, the _TCL\_DBGX_ variable was introduced to support building of debug vs. non-debug versions of Tcl and installing them into the same directory. That may have been a noble goal, but in practice this indirection makes many parts of the build system extremely difficult to modify. This scheme also fails to deal with other identifying suffixes like 's' for a static build or 't' for a threaded build. A number of queries as to the usefulness of _TCL\_DBGX_ have appeared on news:comp.lang.tcl but none produced satisfactory results. The _TCL\_DBGX_ variable should be removed and never spoken of again. # Configure Flags The _--enable-symbols_ should be renamed to _--enable-debug_. Quite a few other software projects use the _--enable-debug_ flag. A Google search turned up no other projects that make use of the _--enable-symbols_ flag. This change would have documentation impact, but it would be minimal. The old flag could be retained for compatibility if a significant number of folks were concerned. The Tcl 8.4 release removes the _--enable-gcc_ flag. This flag introduced a number of problems that are much better solved by simply setting the _CC_ environment variable before running configure. This change has already been incorporated into the CVS and is only mentioned here for the sake of completeness. # Risks Implementing this TIP is by no means an easy task. Build system changes are by far the most dangerous since a broken configuration will not be noticed until someone actually tries to build on the given system. One can only ask for forgiveness before hand. Large scale build system changes will no doubt break something. For this reason, many of the suggested changes should be incorporated into the Tcl 8.5 release. # Alternatives One alternative is to continue to use the existing system. While things would get no worse, they would also get no better. Another alternative is to replace the existing TEA based build system with a build system written in Tcl. This TIP does explore some of the build issues a Tcl based system will face, but tries to focus on improving the existing system instead of replacing TEA. # See Also SourceForge bugs: 219259, 219260, 219330, 420501, 421835, 428627, 464874 SourceForge patch: 465874 # Copyright This document has been placed in the public domain. |
Name change from tip/340.tip to tip/340.md.
|
| < | < | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 340: Const Qualification of Tcl_SetResult's Argument Author: Jan Nijtmans <[email protected]> State: Withdrawn Type: Project Vote: Pending Created: 14-Nov-2008 Post-History: Keywords: Tcl_SetResult Tcl-Version: 8.7 ----- # Abstract As a follow-up of [[27]](27.md), in Tcl 8.6 and Tk 8.6 much work has been done to clean up the remaining places where pointers were not _const_ qualified. The question is, how can we prevent that in the future similar "mistakes" are made. The gcc compiler warning _-Wwrite-strings_ helps in that, therefore this TIP proposes to add that to the CFLAGS\_WARNING flag in Tcl and Tk when using gcc. But for this flag to be introduced, all warnings will have to be eliminated. In the HEAD, this is done already, except for one function: **Tcl\_SetResult**. This function is explicitely mentioned in [[27]](27.md) not to be modified, because it cannot be handled without unsafe casting. This TIP proposes to deprecate **Tcl\_SetResult** in full, and provide a new macro **Tcl\_SetStringResult** in its place. # Rationale The gcc manual mentions for the flag -Wwrite-strings: > When compiling C, give string constants the type _const char[length]_ so that copying the address of one into a non-_const char \*_ pointer will get a warning .... These warnings will help you find at compile time code that can try to write into a string constant, but only if you have been very careful about using const in declarations and prototypes. Otherwise, it will just be a nuisance; this is why we did not make -Wall request these warnings. Now that all Tcl and Tk API's are modified to be very careful about using const, this opens the way to add _-Wwrite-strings_ to CFLAGS\_WARNING when building with gcc. Other extensions can start to do the same, if they want to find out about this type of potential problem. When considering the elimination of the warning when using **Tcl\_SetResult_, I originally see two alternatives: * Change the implementation such that **Tcl\_SetResult**\(_i, s, f_\) does the same as **Tcl\_SetObjResult**\(_i_, **Tcl\_NewStringObj**\(_s_, -1\)\), ignoring the last parameter. > This can be done without an unsafe type cast, but it has the disadvantage that after a \(modified\) **Tcl\_SetResult** call the result is no longer available in interp->result. Older extensions might expect that, those will be silently broken. A the moment, serveral tests fail when doing this, because in various places of the Tcl core there are hack which still support older extensions which still use interp->result directly. It's a little short before Tcl 8.6 to do it now, but it should certainly be considered for the future. * The solution that originally was proposed in this TIP was to leave the **Tcl\_SetResult** implementation as it is, only add a single type cast to prevent a gcc warning. > This violates the [[27]](27.md) conditions, but is in fact not more dangerous than the current situation. It is only dangerous, when the Tcl\_SetResult call has another value than TCL\_STATIC or TCL\_VOLATILE as last argument * The final proposal is a new macro **Tcl\_SetStringResult** that takes over the function of **Tcl\_SetResult**. The function **Tcl\_SetResult** will be deprecated in full. There has been a discussion stating that changing the **Tcl\_SetResult** signature is wrong, because **Tcl\_SetResult** cannot be made const-correct. Most **Tcl\_SetResult** calls use TCL\_STATIC or TCL\_VOLATILE as last argument. In this case, the second argument is expected to be a const. The macro **Tcl\_SetStringResult** takes care of that, since it is implemented in terms of **Tcl\_SetObjResult** and **Tcl\_NewStringObj**. Very few **Tcl\_SetResult** calls have some other value as last argument, most likely TCL\_DYNAMIC. This TIP proposes to deprecate **Tcl\_SetResult** for all values of freeProc. If the value is TCL\_STATIC or TCL\_VOLATILE, there is a new macro **Tcl\_SetStringResult** which can be used in stead. For other values the call can be replaced with **Tcl\_SetStringResult** as well, but then the caller is responsible to free the memory after the **Tcl\_SetStringResult** call. It turns out that Tcl had only 4 deprecated \(as defined by this TIP\) **Tcl\_SetResult** calls, one of them was wrong [Bug 2308236], two of them were in tclTest.c meant to test the **Tcl\_SetResult** function itself. Tk had only 5 such calls. All those calls have been modified now. Tcl and Tk now only calls **Tcl\_SetResult** with either TCL\_STATIC or TCL\_VOLATILE This proposal does not have the "forward compatibility" problem, that extensions using **Tcl\_SetStringResult** compiled. it is even possible for extensions to use **Tcl\_SetStringResult** with Tcl 8.5 and before: #ifndef # define Tcl_SetStringResult(i,s) \ Tcl_SetObjResult(i, Tcl_NewStringObj(s, -1)) #endif # Reference Implementation A new patch will be available in issue \#2315890 <http://sourceforge.net/support/tracker.php/?aid=2315890> . # Copyright This document has been placed in the public domain. |
Name change from tip/341.tip to tip/341.md.
|
| < | < | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | < | > | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 341: Multiple 'dict filter' Patterns Author: Lars Hellström <[email protected]> State: Final Type: Project Vote: Done Tcl-Version: 8.6 Created: 27-Nov-2008 Keywords: Tcl, set intersection Post-History: ----- # Abstract The **key** and **value** forms of **dict filter** are generalised to allow an arbitrary number of patterns. # Specification The two **dict filter** command forms > **dict filter** _dictionary_ **key** _pattern_ > **dict filter** _dictionary_ **value** _pattern_ are generalised to > **dict filter** _dictionary_ **key** ?_pattern_ ...? > **dict filter** _dictionary_ **value** ?_pattern_ ...? and the results are the sub-dictionaries of those keys and values respectively which match at least one of the patterns. # Rationale Although there are **dict** subcommands which allow deleting some keys from a dictionary \(**dict remove**\) and inserting some keys into a dictionary \(**dict replace**\), there is no direct way of requesting the sub-dictionary which only has keys from a given list; if we think of only the set of keys in the dictionary, then we have subcommands for set minus and set union, but none for set intersection. A situation where this would be useful is that the option dictionary for a high-level procedure can contain options meant to be passed on to lower level commands, and it is necessary to extract the subdictionary of options that the lower level command would accept \(since passing one which is not supported would cause it to throw an error\). There is of course already the **dict filter** command, which indeed returns a subdictionary of an existing dictionary, but its **key** form only accepts one **string match** pattern and therefore cannot be used to e.g. select all three of -foo, -bar, and -baz \(it could select both -bar and -baz through the pattern -ba[rz], but that's neither common nor particularly readable\). However, in many instances where this kind of pattern is used \(notably **glob**, **namespace export**, and **switch**\), it is possible to give several such patterns and have it interpreted as the union of the patterns. Were that the case with **dict filter**, the "-foo, -bar, and -baz" problem could be solved as easily as dict filter $opts key -foo -bar -baz which is comparable to dict remove $opts -foo -bar -baz dict replace $opts -foo 1 -bar off -baz 42 and much nicer than the **script** counterpart dict filter $opts script {key val} { ::tcl::mathop::in $key {-foo -bar -baz} } If the **key** form is generalised like this, then it seems appropriate to also generalise the **value** form in the same way to keep the symmetry, even though I have no immediate use-case for that feature. Since it is generally good to Do Nothing Gracefully, the command syntax is also generalised to allow the case of no patterns at all. # Rejected Alternatives A more direct way of meeting the motivating need would be a command **dict select** with the same syntax as **dict remove** \(no pattern matching\) but logic reversed. This would however be so close to **dict filter** ... **key** that extending the syntax of the latter seemed more appropriate. An alternative to allowing multiple patterns with **dict filter** could be to allow a regular expression pattern, since the union of two regular languages is again a regular language. Any syntax that could be picked for that would however on one hand already be rather close to dict filter $opts script {key val} {regexp $RE $key} and on the other it would be rather difficult to read, as the regular expression corresponding to "-foo or -bar or -baz" is ^(-foo|-bar|-baz)$ which it is tempting but incorrect to simplify to "-foo\|-bar\|-baz". # Implementation Notes An implementation exists \(it's a very trivial to modify **dict filter** ... **value** to work this way: just add an inner loop over the list of patterns\); see SF path \#2370575. <https://sourceforge.net/support/tracker.php?aid=2370575> What might be tricky is the case of **dict filter** ... **key**, since this currently has an optimisation for the case of a pattern without glob metacharacters that would be very desirable to keep for the motivating use-case of selecting specific keys from a dictionary. The natural way to do that would be to make the loop over patterns the outer loop and the loop over dictionary entries the inner loop, which is only entered if the current pattern contains metacharacters. Such an optimisation would however have the script-level-visible consequence of having the keys show up in the order of the patterns rather than the order of the original dictionary, so it may be a good idea to also explicitly specify that **dict filter** does not guarantee keys in the result to be in the same order as in the input dictionary. Indeed, a **dict filter** ... **key** that reorders keys according to its pattern arguments could sometimes be useful in interactive situations, as a way of getting selected keys up from in a dictionary: set D {-baz 0 -bar 1 -foo 2} dict filter $D key -foo -bar * On the other hand, this effect can mostly be obtained through use of **dict merge** already: dict merge {-foo x -bar x} $D # Copyright This document has been placed in the public domain. |
Name change from tip/342.tip to tip/342.md.
|
| < | < | | | | | | | | > | | | | | | | | | | | < < | > > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 342: Dict Get With Default Author: Lars Hellström <[email protected]> State: Draft Type: Project Vote: Pending Tcl-Version: 8.7 Created: 27-Nov-2008 Keywords: dictionary, default value Post-History: ----- # Abstract A new subcommand of **dict** is proposed, which returns a dictionary value if it exists and returns a per-call default otherwise. # Specification The **dict** command will get a new subcommand > **dict getwithdefault** _dictionary_ _key_ ?_key_ ...? _value_ \(I consider the name of this subcommand very much open for discussion\) which modulo error messages behaves like proc dict_getwithdefault {D args} { if {[dict exists $D {*}[lrange $args 0 end-1]]} then { dict get $D {*}[lrange $args 0 end-1] } else { lindex $args end } } i.e., it returns the value from the _dictionary_ corresponding to the sequence of _key_s if it exists, or the default _value_ otherwise. As with **dict exists**, it is OK \(and will cause the default _value_ to be returned\) if one of the _key_s is missing from its dictionary, but an error is thrown if this path of keys cannot be traversed because the value associated with the previous key is not a dictionary. # Rationale It is clear that getting a value from a dictionary if it exists and using a default otherwise is a common operation, but it is also clear that this can be carried out with a combination of existing Tcl commands. Hence the issue is whether a new subcommand for this improves efficiency and convenience of this operation enough to justify the possible bloat it brings. ## Alternative Methods One approach that has been suggested for providing default values is to combine **dict get** with **dict merge**, like so: dict get [dict merge {-apa bar} $D] -apa This approach is however appropriate mainly in situations where several keys are given fixed defaults simultaneously. Compared to **dict getwithdefault**, it has the following disadvantages: * It cannot be used for keys in nested dictionaries. * It takes time proportional to the size of the dictionary, even when only one value is inspected. Since **dict filter key** has an optimisation for this kind of situation, there are apparently maintainers which consider such differences relevant. * The "one **dict merge** early providing defaults for all keys" approach cannot deal with keys that have dynamic defaults, e.g. that the default for option -foo is the effective value of option -bar. Hence although **dict merge** is sometimes appropriate for providing defaults, it is not a universal solution. The basic approach is instead to, as in the **dict\_getwithdefault** proc above, first use **dict exists** and then **dict get** if the value existed. Problems with this approach are: * It is redundant: already **dict exists** retrieves the value, but doesn't return it, so **dict get** has to look it up all over again. * It is bulky: if the value in dictionary _D_ of option **-apa** \(or its default **bar**\) is to be passed as an argument to the command **foo**, then the complete command is foo [if {[dict exists $D -apa]} then {dict get $D -apa}\ else {return -level 0 bar}] > or foo [expr {[dict exists $D -apa] ? [dict get $D -apa] : "bar"}] > which many programmers would find objectionable. The **dict getwithdefault** counterpart is merely foo [dict getwithdefault $D -apa bar] The only way to avoid the redundance of an extra look-up seems to be to combine **dict get** with **catch**, like so: if {[catch {dict get $D -apa} value]} then {set value bar} else {set value} but this has the disadvantage of hiding other sources of error, such as _D_ not being a dictionary in the first place. This kind of error in a normal processing path is also considered poor style by some. ## Implementation Choices Even if it is deemed appropriate to have a dedicated subcommand of **dict** for this, it could be argued that it needn't be part of the compiled Tcl core; since **dict** is an ensemble, anyone can extend it at the script level and "the core can do without this bloat". However, it turns out than an in-core implementation is very easy whereas the alternatives are not so easy. Concretely, the necessary DictGetWithDefaultCmd is a trivial modification of DictExistsCmd, to take one extra argument after the _key_s and change the final Tcl_SetObjResult(interp, Tcl_NewBooleanObj(valuePtr != NULL)); to Tcl_SetObjResult(interp, valuePtr != NULL ? valuePtr : objv[objc-1]); It is nowhere near as easy to do this in a well-behaved extension, since DictExistsCmd relies on TclTraceDictPath to do most of the work, and the latter is AFAICT at best available in the internal stubs table. A script-level implementation is certainly possible, but the minute details of producing core-looking error messages in this case appears considerable both compared to the functional parts of the command and compared to the amount of code needed to do it in the core. # Reference Implementation An implementation is provided on SF, in patch \#2370575. <https://sourceforge.net/support/tracker.php?aid=2370575> # Copyright This document has been placed in the public domain. |
Name change from tip/343.tip to tip/343.md.
|
| < | < | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 343: A Binary Specifier for [format/scan] Author: Alexandre Ferrieux <[email protected]> State: Final Type: Project Vote: Done Created: 03-Dec-2008 Post-History: Keywords: Tcl,binary Tcl-Version: 8.6 ----- # Abstract This TIP proposes to add a %b specifier to the **format** and **scan** commands for working with integers in base-2 representation. # Background The **format** and **scan** commands already have decimal, hexadecimal, and octal support, but people wanting binary today resort to a hack, namely going hexadecimal first and then **string map**ping the hex digits to their four-bits binary representations. We also already have the "0b" notation as input for **expr**. This lack is inelegant. # Proposed Change This TIP proposes to reuse the existing binary representation machinery to expose a new **%b** specifier: format %b 5 => 101 scan 000101 %b x;set x => 5 The good properties of the existing code make the addition really painless, in that it automagically combines with the size \(l,ll\), width \(digits\), and prefix \(\#\) modifiers: format %#06b 5 => 0b0101 format %llb [expr {(2**72-1)/7}] 1001001001001001001001001001001001001001001001001001001001001001001001 # Rationale That is really low-hanging fruit. All the pieces are in place, it's just a matter of exposition. The binary representation is a nice pedagogic tool, and having it handy \(rather than with a hack\) is a bonus. # Reference Implementation See Patch 2368084 <https://sourceforge.net/support/tracker.php?aid=2368084> . # Copyright This document has been placed in the public domain. |
Name change from tip/344.tip to tip/344.md.
|
| < | < | | | | | | | > | | | | | | | | | | | | | | > | 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 | # TIP 344: Bring TCP_NODELAY and SO_KEEPALIVE to socket options Author: Alexandre Ferrieux <[email protected]> State: Draft Type: Project Vote: Pending Created: 31-Dec-2008 Post-History: Tcl-Version: 8.7 ----- # Abstract Just expose to script level, via **fconfigure**, the two most important setsockopt\(\) use cases: TCP\_NODELAY \(disabling the Nagle agorithm\) and SO\_KEEPALIVE \(sending automatic keepalives\). # Background & Rationale Currently, there is no way to set nodefault values to a Tcl socket's underlying socket options TCP\_NODELAY and SO\_KEEPALIVE. That is frustrating because all TCP stacks support setsockopt\(\). Of these two options, the most important I guess is TCP\_NODELAY. Indeed, the Nagle algorithm being on by default may introduce unwanted latencies in some specific cases. This TIP does not try to argument about the prevalence of these cases; the ubiquity of setsockopt\(TCP\_NODELAY\) suffices to justify exposing it to script level. # Proposed Change This TIP proposes to add two boolean [fconfigure] options to sockets: **-nodelay** \(or **-nonagle**, or **-nagle**, take your pick\) and **-keepalive**. # Reference Implementation Pretty trivial; will be provided shortly after validation. The code has even been in place for a long time, though only in the Windows-specific part, and commented/ifdef'ed out... # Copyright This document has been placed in the public domain. |
Name change from tip/345.tip to tip/345.md.
|
| < | < | | | | | | | | > | | | | | | | | | | | > | 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 | # TIP 345: Kill the 'identity' Encoding Author: Alexandre Ferrieux <[email protected]> State: Draft Type: Project Vote: Pending Created: 05-Feb-2009 Post-History: Keywords: Tcl,encoding,invalid UTF-8 Tcl-Version: 8.7 ----- # Abstract This TIP proposes to remove the 'identity' encoding which is the Pandora's Box of invalid UTF-8 string representations. # Background The contract of string representations in Tcl states that the _bytes_ field \(the **strep**\) of a Tcl\_Obj must be a valid UTF-8 byte sequence. Violating it leads at best to inconsistent and shimmer-sensitive string comparisons. Fortunately, nearly all of the Tcl code takes careful steps to enforce it. With one exception: the 'identity' encoding. Indeed, this encoding allows any byte sequence to be copied verbatim into the strep of a value, as a side-effect of a strep computation on a ByteArray with [**encoding system**]=="identity", or through [**encoding convertfrom identity**]. Hence an invalid UTF-8 sequence can easily make it to the strep and start wreaking havoc. # Proposed Change This TIP proposes to simply close that single window to the dark side. # Rationale The risk of compatibility breakage is inordinately mild in that case, since it has only ever been documented in tcltest. # Reference Example See Bug 2564363 <https://sourceforge.net/support/tracker.php?aid=2564363> # Copyright This document has been placed in the public domain. |
Name change from tip/346.tip to tip/346.md.
|
| < | < | | | | | | | | > | | | | | | | | | | | | | | | > | 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 | # TIP 346: Error on Failed String Encodings Author: Alexandre Ferrieux <[email protected]> State: Draft Type: Project Vote: Pending Created: 02-Feb-2009 Post-History: Keywords: Tcl,encoding,convertto,strict,Unicode,String,ByteArray Tcl-Version: 8.7 ----- # Abstract This TIP proposes to raise an error when an encoding-based conversion loses information. # Background Encoding-based conversions occur e.g. when writing a string to a channel. In doing so, Unicode characters are converted to sequences of bytes according to the channel's encoding. Similarly, a conversion can occur on request of the ByteArray internal representation of an object, the target encoding being ISO8859-1. In both cases, for some combinations of Unicode char and target encoding, the mapping is lossy \(non-injective\). For example, the "e acute" character, and many of its cousins, is mapped to a "?" in the 'ascii' target encoding. Also, Unicode chars above \\u00FF get 'projected' onto their low byte in the ISO8859-1 ByteArray conversion. This loss of information, in the first case, introduces unnoticed i18n mishandlings. In the second case, it makes it unreliable to do pure-ByteArray operations on objects unless they have no string representation. This induces unwanted and hard-to-debug performance hits on bytearray manipulations when people add debugging **puts**. # Proposed Change This TIP proposes to make this loss conspicuous. For the first use case, the idea is to introduce a **-strict** option to **encoding convertto**, that would raise an explicit error when non-mappable characters are met. Lossy conversions during channel I/O would also fail if a **-strictencoding true** [fconfigure option] is set. For the second case, we simply want the conversion to fail, like does the Listification of an ill-formed list. In both cases, the change consists of letting the proper internal conversion routine like **SetByteArrayFromAny** return TCL\_ERROR. # Rationale The second case does imply a Potential Incompatibility, since currently SBFA is documented to always return TCL\_OK. However, it is felt that virtually all cases that are sensitive to this, are actually half-working in a completely hidden manner. Hence the global effect is a healthy one. # Reference Example See Bug 1665628 <https://sourceforge.net/support/tracker.php?aid=1665628> . # Copyright This document has been placed in the public domain. |
Name change from tip/347.tip to tip/347.md.
|
| < | < | | | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 347: Align 'string is ...' to Type-Conversion Functions in 'expr' Author: Jos Decoster <[email protected]> State: Withdrawn Type: Project Vote: Pending Created: 09-Feb-2009 Post-History: Discussions-To: news:comp.lang.tcl Keywords: Tcl Tcl-Version: 8.7 Obsoleted-By: 395 ----- # Abstract The **string** command supports tests for a number of Tcl's basic types, for example, integers, doubles, and booleans. The **tcl::mathfunc** mathematical functions provides sevaral functions to limit the number of bits used in integer numbers. This TIP proposes to align both groups of functions for **int**, **long**, **wide** and **entier**. # Rationale The **string** command includes tests for the common Tcl types: **string is boolean**, **string is double** and **string is integer**. Some of the integer ranges used in Tcl internals are missing from the list, making it difficult for an input validation procedure to determine whether, in fact, a string contains a valid integer number to be used for that specific Tcl command. Ranges already present are: * **integer** * **wideinteger** Missing ranges are: * **long** * **entier** The **::tcl::mathfunc** mathematical functions provides sevaral functions to limit the number of bits used in integer numbers. Some of the integer ranges used in Tcl internals are missing from the list, and other check an unexpected range. Functions already present are: * **wide** * **entier** Functions already present but with unexpected behavior are: * **int** actually does a **long** conversion Missing functions are: * **long** Providing a **string is** function for every integer range used in Tcl internals will make it possible to check every argument in input validation procedures before calling a Tcl command. Providing **::tcl::mathfunc** for every integer range used in Tcl internals will make it possible to create values in a valid range before calling a Tcl command. Having the same integer range names in the **string is** functions and in the **::tcl::mathfunc** when they act on the same integer ranges would make the commands easier to recognise. # Specification This document proposes: * augmenting the **string is** command with a **string is long** that functions the same as **string is integer** in every respect except for the fact that it accepts any string containing a substring that is valid as a long integer \(that is, acceptable to _Tcl\_GetLongFromObj_\) possibly surrounded by whitespace. * augmenting the **string is** command with a **string is entier** that functions the same as **string is integer** in every respect except for the fact that it accepts any string containing a substring that is valid as a bignum integer \(that is, acceptable to _Tcl\_GetBignumFromObj_\) possibly surrounded by whitespace. * modifying the **::tcl::mathfunc::int** to convert to an integer \(that is, acceptable to _Tcl\_GetIntFromObj_\). * adding the **::tcl::mathfunc::long** to convert to a long integer \(that is, acceptable to _Tcl\_GetLongFromObj_\). * keeping the **string is integer** command as it can be abbreviated to **string is int** to align with **::tcl::mathfunc::int**. * keeping the **string is wideinteger** command as it can be abbreviated to **string is wide** to align with **::tcl::mathfunc::wide**. # Compatibility On platforms where a **long_ variable has a different range than an **int** variable, renaming the **::tcl::mathfunc::int** to **::tcl::mathfunc::long** will let code like: \| set a [expr {int($b)}] behave differently for **long** values outside the **int** range. # Alternatives The **bignum** was rejected in favor of **entier** because **entier** is already used in **::tcl::mathfunc::entier**. # Reference Implementation Patches that implement the above, provide test cases for it, and update documentation to include it are available at SourceForge as Tcl Patch \#2581150<http://sourceforge.net/tracker2/?func=detail&aid=2581150&group_id=10894&atid=310894> . # Copyright This document has been placed in the public domain. |
Name change from tip/348.tip to tip/348.md.
|
| < | < | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 348: Substituted 'errorstack' / 'traceback' Author: Alexandre Ferrieux <[email protected]> State: Final Type: Project Vote: Done Created: 26-Feb-2009 Post-History: Keywords: Tcl,debugging Tcl-Version: 8.6 ----- # Abstract This TIP proposes to add an **errorstack** options dict entry and associated **info** subcommand, giving a "substituted" traceback similar to Python's or gdb's ones. # Background The **::errorInfo** variable is a valuable tool for debugging; however, it yields mostly static information regarding each level of procedure call, as it only gives the static text \(extracted from the source\) at the call site. This leads to frustrating situations, like when an error occurs at a deep level of a recursive function, **::errorInfo** repeatedly reporting "f $x [foo [bar]]" or similar un-substituted commands. In other languages, the traceback is more useful in that it contains the actual values passed as arguments. # Proposed Change This TIP proposes to create an **-errorstack** options dictionary entry, and an associated **info errorstack** ?_interp_? command returning a list containing the [**info level** 0] lists of command-and-args at each stack frame level at the time of error unwinding. # Rationale In a natural implementation, its construction is analogous to that of **::errorInfo**, which is built incrementally, one level at a time while popping back from the error site. The only differences are that: 1. dynamic arglists \(from [**info level** 0]\) are stored, 2. the result is a true list built by \(the equivalent of\) **lappend**, and 3. the granularity is coarser than with **::errorInfo** since there is just one element per stack frame level \(and not for intervening **while** or **foreach** constructs\) and no adornment like "... while executing ..." Measurements show that the performance hit of maintaining the error stack is small, being under 5% for realistic error stack sizes, and hits only the error cases. To achieve this speed, the list-growing is done carefully, reusing earlier optimizations made on list operations for the in-place case, so that in routine use the allocated Tcl\_Obj, internal representation, and element array storage backing the list never change. This way, even code heavily relying on **catch** across dozens of stack frame levels won't noticeably suffer from the error stack machinery. # Definition The error stack is an even-sized list alternating tokens and parameters. Tokens are currently either **CALL** or **UP**, but other values may be introduced in the future; **CALL** indicates a procedure call, and its parameter is the corresponding [**info level** 0]; **UP**' indicates a shift in variable frames generated by **uplevel** or similar, and applies to the previous **CALL** item: > CALL \{foo a\} UP 1 CALL \{bar b\} CALL \{baz c\} UP 2 CALL \{gnu d\} CALL \{gnats e\} The above value indicates that [foo a] was called by [bar b] through [uplevel 1]. Similarly, [baz c] was itself lifted to toplevel by an [uplevel 2] in [gnu d]. # Reference Implementation The reference implementation can be found on SourceForge<https://sourceforge.net/support/tracker.php?aid=2868499> . An earlier, extremely slow, pure-Tcl proof of concept based on write traces on **::errorInfo** can be found on the Wiki<http://wiki.tcl.tk/traceback> . # Copyright This document has been placed in the public domain. |
Name change from tip/349.tip to tip/349.md.
|
| < | < | | | | | | | > | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 349: New "-cargo" option for every Tk widget Author: Zbigniew Baniewski <[email protected]> State: Draft Type: Project Tcl-Version: 8.7 Vote: Pending Created: 17-Apr-2009 Post-History: ----- # Abstract This TIP proposes adding a **-cargo** option to every Tk widget that will be kept free for code that uses the widget to use as it sees fit; the Tk library will assign no interpretation to the option. # Proposal TCL users have long been at a disadvantage not having a possibility to attach arbitrary widget-related values \(e.g., "tooltip"-texts\) directly to widget, being forced to use workarounds \(e.g. external variables to hold the data\) or even entire additional packages/frameworks \(like Snit\) exactly because of the lack of the proposed option. So the proposal is "solutions instead of workarounds": let's introduce the option - further named "-cargo" \(the name taken from Clipper\) - which will cancel the current need for fixes of different kind. The option should allow to access a string field \(or even better: a dictionary\), allowing to keep there any widget-related data, choosen by script creator. It's value should be accessible both by "cget" and "percent substitution" \(like "%C"\). # Rationale In a talk at news:comp.lang.tcl everyone - or almost everyone - posting in the appropriate threads, appreciated the proposed solution as useful. There were some fears about possible "clashes" while using that option \(or that the proposed option will be even "too useful"\). I would to mention here, that "cargo" idea has been taken from Clipper, where - during over 20 past years - there is no evidence at all of any "clashes" \(neither of any other damage\) only because of availability of such option. Being sure, that TCL programmers aren't less skilled than those Clipper guys, I cannot describe such fears differently, than as not reasonable ones. So because such option has been successfully tested in other language \(there are no complaints from Clipper programmers about any "cargo"-harmness\), there's no need for "prophecies" of the type "it will do damage", because there has been proved exactly the contrary. Some more possible usage gave Bryan Oakley in his post: > What sort of data would I potentially keep with a widget? Perhaps an index that points to context sensitive help. Or, I might keep an undo stack, or a copy of the original value. Think of a label widget that automatically truncates it's text and adds "..." if the widget is resized smaller than it's preferred size -- you need to keep the unadulterated original value that you can refer to as the widget grows and shrinks. Better to keep that with the widget than in a global variable, IMO. Or, I could use it to keep track of a "dirty" bit that gets set when the original value of a radiobutton or checkbutton changes. Or I could store a database primary key that points to where the data for the widget came from. I believe, that's not all, because we cannot predict today, what other useful things can be done with option of such "universal" \(not "targetted"\) nature. Two things for sure: a\) It'll make the life of every TCL-scriptor easier, b\) Its use won't be obligatory, if someone will be afraid of "clashes" possibility, or something like this. # License This document has been placed in the public domain. |
Name change from tip/35.tip to tip/35.md.
|
| < | < | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 35: Enhanced Support for Serial Communications Author: Rolf Schroedter <[email protected]> State: Final Type: Project Vote: Done Created: 06-Jun-2001 Post-History: Tcl-Version: 8.4 ----- # Abstract Tcl's support for RS-232 is very rudimentary. Mainly it allows to setup the communication rate [fconfigure -mode] and to read and write data with the standard Tcl functions. Real serial communications are often more complex. Therefore it is proposed to add support for hardware and software flow control, polling RS-232 \(modem\) status lines, and watching the input and output queue. This is all to be implemented via additional [fconfigure] options. # Rationale There is an undamped interest in serial communications, because it's very easy to connect external hardware to a computer using the RS-232 ports. However Tcl's support for serial communications is not complete. Real applications often need more than setting the baud rate and to read/write data bytes. Especially if the external hardware is slow or the communication rate is high one needs support for flow-control \(hard- and software\). These features are provided by the operating system drivers, but Tcl's [fconfigure] doesn't support it. On the the other hand there are cases that the external hardware makes static use of the RS-232 signals to signal external events via the modem status lines or even to be powered by the RS-232 control lines. Additionally for non-blocking serial I/O it may be interesting for the Tcl application to know about the status of the input and output queues to read a fixed size block or to support communication timeouts. At this opportunity it is proposed to move the documentation of the serial port fconfigure options form the _open.n_ man-page to _fconfigure.n_. # Specification It is proposed to have following set of [fconfigure] options for serial communications: -mode baud,parity,data,stop: _\(Windows and Unix\)_. Already implemented. -handshake mode: _\(Windows and Unix\)_. This option is used to setup automatic handshake control. Note that not all handshake modes maybe supported by your operating system. The mode parameter is case-independent. > If mode is _none_ then any handshake is switched off. _rtscts_ activates hardware handshake. For software handshake _xonxoff_ the handshake characters can be redefined with [fconfigure -xchar]. An additional hardware handshake _dtrdsr_ is available only for Windows. There is no default handshake configuration, the initial value depends on your operating system settings. The -handshake option cannot be queried, because the operating system settings may be ambiguous. -xchar \{xonChar xoffChar\}: _\(Windows and Unix\)_. This option is used to change the software handshake characters. Normally the operating system default should be DC1 \(0x11 hex\) and DC3 \(0x13 hex\) representing the ASCII standard XON and XOFF characters. When queried -xchar returns a list of two characters representing the XON and XOFF characters respectively. -timeout msec: _\(Windows and Unix_. This option is used to set the timeout for blocking read operations. It specifies the maximum interval between the receiption of two bytes in milliseconds. For Unix systems the granularity is 100 milliseconds. The -timeout option does not affect write operations or nonblocking reads. This option cannot be queried. -ttycontrol \{signal boolean signal boolean ...\}: _\(Windows and Unix\)_. This option is used to setup the handshake output lines permanently or to send a BREAK over the serial line. The _signal_ names are case-independent. > \{RTS 1 DTR 0\} sets the RTS output to high and the DTR output to low. For POSIX systems \{BREAK 1\} sends a break signal \(zero-valued bits\) for 0.25 to 0.5 seconds and \{BREAK 0\} does nothing. For Windows the break is enabled and disabled with \{BREAK 1\} and \{BREAK 0\} respectively. It's not a good idea to change the RTS \(or DTR\) signal with active hardware handshake _rtscts_ \(or _dtrdsr_\). The result is unpredictable. The -ttycontrol option cannot be queried. -ttystatus: _\(Windows and Unix\)_. The -ttystatus option can only be queried. It returns the current modem status and handshake input signals. The result is a list of signal,value pairs with a fixed order, e.g. \{CTS 1 DSR 0 RING 1 DCD 0\}. The _signal_ names are returned upper case. -queue: _\(Windows and Unix\)_. The -queue option can only be queried. It returns a list of two integers representing the current number of bytes in the input and output queue respectively. -sysbuffer inSize: -sysbuffer \{inSize outSize\}: _\(Windows only, Unix ?\)_. This option is used to change the size of Windows system buffers for a serial channel. Especially at higher communication rates the default input buffer size of 4096 bytes can overrun for latent systems. The first form specifies the input buffer size, in the second form both input and output buffers are defined. -pollinterval msec: _\(Windows only\)_. Already implemented. -lasterror: _\(Windows only, Unix?\)_. Already implemented for Windows. # Implementation Details For Unix \(_termios.h_\) systems the proposed changes are very straight forward, because Unix channels can be configured blocking or non-blocking. One only needs to add the serial [fconfigure] options calling the appropriate _ioctl\(\)_ functions to configure the serial port. For Windows reading and writing files is generally blocking. Especially with activated handshake the serial communication can stop forever. Therefore the Windows implementation needs at least a writing thread preventing Tcl's main application to block. Additionally Windows provides a reach set of special APIs for serial communication which needs to be translated to [fconfigure] options. There is one special point about Windows: For making multiple threads accessing a serial port, it needs to be opened with the OVERLAPPED flag set. Tcl detects a serial port only after opening it without the OVERLAPPED flag. Therefore this port has to be reopened, which requires a little change to _tclWinChan.c_ and _tclWinPort.h_. Macintosh systems - ? # Changed Files tclUnixChan.c: Add [fconfigure] options. tclWinPort.h: Declare a new function _TclWinSerialReopen\(\)_ tclWinChan.h: Call _TclWinSerialReopen\(\)_ after detecting the serial port. tclWinSerial.c: Partial rewrite of Tcl's serial driver. The current implementation only performs blocking output. Add [fconfigure] options. fconfigure.n: Serial [fconfigure] options should be documented here. open.n: Serial port filenames are documented here. Add a link to [fconfigure] for additional serial options. # Timeouts It has also been proposed to add a [fconfigure -timeout] option specifying read and write timeouts. Together with a blocking read a timeout could be used to wait for an expected number of data bytes from the serial port. There are two arguments against timeouts: 1. Adding timeout to blocking I/O at the driver level radically changes the behaviour of write operations. This adds a lot of oddity to serial communications. 2. Timeouts can easily be implemented at Tcl level using non-blocking I/O together with Tcl's event loop. Additional support is given by [fconfigure -queue]. July 03, 2001: On the other hand timeout for read operations can easily be implemented in a cross-platform way by using the VMIN/VTIME settings for Unix and the COMTIMEOUTS for Windows. That's why the author finally agrees with the -timeout proposal. # Restore settings at close ? It has also been proposed that Tcl should not restore the original serial ports settings at [close $chan]. IMO it doesn't hurt, because anyway an application should care about setting up the serial port properly before using. Without restoring a Tcl script could be used as a _poor_ stty, considering however that Tcl does not provide a complete control over serial settings. So the proposal is to remove the current save/restore mechanism from the Unix implementation for serial ports. # Source code patches The patches have been uploaded to the sourceforge patch tracker: ID=438509 TIP\#35 Patches: Serial Port Enhancements file=tip35patch.tgz # Copyright This document has been placed in the public domain. |
Name change from tip/350.tip to tip/350.md.
|
| < | < | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | < > | | < | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 350: Tcl Database Connectivity - Corrigenda Author: Kevin B. Kenny <[email protected]> State: Draft Type: Informative Created: 18-Apr-2009 Post-History: Vote: Pending Obsoletes: 308 ----- # Abstract This TIP defines a common database access interface for Tcl scripts. It is an update to [[308]](308.md) to take into account experience gained since that TIP was written. Note that this TIP does _not_ repeat the contents of that one, which is mostly correct apart from the changes described in this document. # Summary of Changes Implementation experience on Tcl Database Connectivity [[308]](308.md) has exposed several issues with its specification that require editorial corrections. In brief: 1. The error codes returned from TDBC drivers are detailed in such a way as to make them more usable in the **try** command. 1. The **starttransaction** method on a database connection is renamed, **begintransaction** 1. The **execute** method on a statement, and all of the methods that invoke it \(**allrows** and **foreach** on database connections\) changes its behaviour in the case where a bound variable in its SQL code refers to a Tcl variable that is an array, or a read trace on the associated variable fails. 1. The order of arguments on the **foreach** methods on database connections, statements and result sets is changed. 1. The _statementClass_ and _resultSetClass_ instance variables, and the _init_ method of connections, statements and result sets, are deprecated; a new initialization API is provided. 1. A Tcl command, **tdbc::mapSqlState**, and a C function, **Tdbc\_MapSqlState** are provided for the convenience of driver writers. # Introduction The actual implementation of TDBC and three database drivers for it has revealed a handful of mistakes in the TDBC specification [[308]](308.md). The purpose of this TIP is to correct those errors and promulgate a specification that matches TDBC as implemented. # Specification ## Error Codes Whenever a TDBC driver reports an error in interacting with an underlying database, it SHOULD set the interpreter error code to a list of at least four elements. The first element should be the constant string **TDBC**. The second should be an 'error class' chosen from the list below. The third should be the \(usually five-character\) SQL state that the database reported, or the constant string **HY000** if the SQL state cannot be determined. \(In the latter case, the error class should be **GENERAL\_ERROR**.\) The fourth element should be the name of the TDBC driver that reported the error. Any elements beyond the fourth SHOULD give further details \(for example an error code returned by a native API\), and are driver dependent. The permissible values for the error class are as follows. Note that each one corresponds to the first two characters of a five-character 'SQL state' that is common to most SQL database API's; the SQL state corresponding to the class is also given. SQL State Prefix Error Class -------------------------------------------------------- 00 UNQUALIFIED_SUCCESSFUL_COMPLETION 01 WARNING 02 NO_DATA 07 DYNAMIC_SQL_ERROR 08 CONNECTION_EXCEPTION 09 TRIGGERED_ACTION_EXCEPTION 0A FEATURE_NOT_SUPPORTED 0B INVALID_TRANSACTION_INITIATION 0D INVALID_TARGET_TYPE_SPECIFICATION 0F LOCATOR_EXCEPTION 0K INVALID_RESIGNAL_STATEMENT 0L INVALID_GRANTOR 0P INVALID_ROLE_SPECIFICATION 0W INVALID_STATEMENT_UN_TRIGGER 20 CASE_NOT_FOUND_FOR_CASE_STATEMENT 21 CARDINALITY_VIOLATION 22 DATA_EXCEPTION 23 CONSTRAINT_VIOLATION 24 INVALID_CURSOR_STATE 25 INVALID_TRANSACTION_STATE 26 INVALID_SQL_STATEMENT_IDENTIFIER 27 TRIGGERED_DATA_CHANGE_VIOLATION 28 INVALID_AUTHORIZATION_SPECIFICATION 2B DEPENDENT_PRIVILEGE_DESCRIPTORS_STILL_EXIST 2C INVALID_CHARACTER_SET_NAME 2D INVALID_TRANSACTION_TERMINATION 2E INVALID_CONNECTION_NAME 2F SQL_ROUTINE_EXCEPTION 33 INVALID_SQL_DESCRIPTOR_NAME 34 INVALID_CURSOR_NAME 35 INVALID_CONDITION_NUMBER 36 CURSOR_SENSITIVITY_EXCEPTION 37 SYNTAX_ERROR_OR_ACCESS_VIOLATION 38 EXTERNAL_ROUTINE_EXCEPTION 39 EXTERNAL_ROUTINE_INVOCATION_EXCEPTION 3B SAVEPOINT_EXCEPTION 3C AMBIGUOUS_CURSOR_NAME 3D INVALID_CATALOG_NAME 3F INVALID_SCHEMA_NAME 40 TRANSACTION_ROLLBACK 42 SYNTAX_ERROR_OR_ACCESS_RULE_VIOLATION 44 WITH_CHECK_OPTION_VIOLATION 45 UNHANDLED_USER_DEFINED_EXCEPTION 46 JAVA_DDL 51 INVALID_APPLICATION_STATE 53 INSUFFICIENT_RESOURCES 54 PROGRAM_LIMIT_EXCEEDED 55 OBJECT_NOT_IN_PREREQUISITE_STATE 56 MISCELLANEOUS_SQL_OR_PRODUCT_ERROR 57 RESOURCE_NOT_AVAILABLE_OR_OPERATOR_INTERVENTION 58 SYSTEM_ERROR 70 INTERRUPTED F0 CONFIGURATION_FILE_ERROR HY GENERAL_ERROR HZ REMOTE_DATABASE_ACCESS_ERROR IM DRIVER_ERROR P0 PGSQL_PLSQL_ERROR S0 ODBC_2_0_DML_ERROR S1 ODBC_2_0_GENERAL_ERROR XA TRANSACTION_ERROR XX INTERNAL_ERROR anything else UNKNOWN_SQLSTATE The reason for structuring the error codes in this way is to make errors more accessible to the **try** command [[329]](329.md). For instance, a Tcl script that wishes to detect and handle division by zero in a SQL statement might look like: try { $statement foreach row { # ... process the row } } trap {TDBC DATA_EXCEPTION 22012} { puts "Division by zero!" } Since the previous specification [[308]](308.md) left the error code unspecified, this change is not expected to impact any client code. ## Transaction Control The **begintransaction** method was inadvertently called, **starttransaction** in the TDBC specification. Therefore, the word **starttransaction** should be replaced with **begintransaction** wherever it appears. This change will break no existing code; no **starttransaction** method has been defined for any TDBC driver. ## The **execute** Method of a Statement - Variable Substitution The rule that an array variable provided as a bound value to a substituent in a SQL statement MUST result in an error has proven to be awkward to implement in practice. Moreover, the original specification [[308]](308.md) fails to indicate what happens if a read trace on one of a statement's bound variables throws an error. The sentence, > An array variable provided to a substituent MUST result in an error. is therefore to be replaced with: > An array variable provided to a substituent, or a variable in which substitution results in an error being reported by a read trace, MUST result in a NULL value being provided. This change is expected to have minimal impact on existing code; the behaviour being described is simply providing a NULL value for a case that was an error before \(an array where a scalar is expected\) and a case that was unspecified before \(an error within a variable trace\). ## The _foreach_ Methods The syntax of the _foreach_ method of connections, statements, and result sets in the original specification contains editorial errors. The correct syntax is: > _dbHandle_ **foreach** ?**-as** **lists**\|**dicts**? ?**-columnsvariable** _varName_? ?--? _varName_ _sql_ ?_dictionary_? _script_ > _statement_ **foreach** ?**-as** **lists**\|**dicts**? ?**-columnsvariable** _varName_? ?--? _varName_ ?_dictionary_? _script_ > _resultset_ **foreach** ?**-as** **lists**\|**dicts**? ?**-columnsvariable** _varName_? ?--? _varName_ _script_ This change represents an editorial correction; the reference implementation functioned in this way even prior to the acceptance of the original specification [[308]](308.md). ## The Constructor Patterns The _statementClass_ variable, and the **init** method, are no longer recommended for use in the constructors of connection classes. Instead, the recommended pattern is that a connection class SHOULD implement a **statementCreate** method that accepts the fully qualified name of the command that is to represent the statement, the connection handle and the SQL statement, and returns a handle to the statement object. The usual way to do so is with a forwarded method: forward statementCreate ::driver::statement create If the **statementCreate** method is not present, the default one looks for a variable named _statementClass_ in the connection object, and invokes its **create** command. In this way, drivers that are written to the original specification continue to operate. Similarly, the _resultSetClass_ variable, and the **init** method, are no longer recommended for use in the constructors of statement classes. Instead, the statement class SHOULD implement a **resultSetCreate** method that accepts the fully qualified name of the command that will represent the result set, the statement handle, and the parameters to the **prepare** method. Once again, this method will usually simply be forwarded to the appropriate constructor: forward resultSetCreate ::driver::resultSet create Once again, backward compatibility is provided by a **resultSetCreate** method in the base class. This method looks for a _resultSetClass_ variable in the statement instance, and interprets it as a class name, invoking the _create_ method in that class. _Rationale:_ These changes eliminate several jumps among methods with **uplevel** calls, and yield both simpler code and improved performance. ## SQL State Mapping For the convenience of drivers that deal with database APIs that provide a standard SQL dtate in the event of errors, a Tcl command, **tdbc::mapSqlState** is provided. This command accepts a \(usually five character\) SQL state, and returns the error class that should go in the second element of the error code. The mapping is described in the table in the **Error Codes** section above. Similarly, A C function is provided: > const char \* **Tdbc\_MapSqlState**\(const char \*_sqlstate_\); This call looks up the given _sqlstate_ and returns its error class according to the table. # License This file is explicitly released to the public domain and the author explicitly disclaims all rights under copyright law. |
Name change from tip/351.tip to tip/351.md.
|
| < | < | | | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | < > | | | < > | | | | < > | | | < | > | > | 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 | # TIP 351: Add Striding Support to lsearch Author: Peter da Silva <[email protected]> Author: Donal K. Fellows <[email protected]> Author: Harald Oehlmann <[email protected]> Author: Andreas Leitgeb <[email protected]> State: Draft Type: Project Vote: Pending Created: 09-Jul-2009 Post-History: Tcl-Version: 8.7 ----- # Abstract This TIP allows the searching of lists that are grouped into collections of several elements. # Rationale When operating on strided lists \(for example key-value lists\) it's normal to convert them between lists and arrays and back again. If it was possible to efficiently perform a strided search of the list it would be possible to \(for example\) search just the keys and ignore the values. Indeed, Tcl has a long tradition of working with lists which are structured into groups through **foreach** and **array get**, and this is strengthened further with dictionaries [[111]](111.md) and striding sorts [[326]](326.md). However, there is currently no facility for searching such lists; this TIP proposes fixing this. # Proposed Change We propose adding a **-stride** option to **lsearch**, by exact analogy with the option added to **lsort** in [[326]](326.md), whose semantics it should closely match. If **-stride** is supplied, the list will be treated as consisting of groups of grpSize elements. The search will be operated within this group as it is a first level of nested lists \(see _Conceptual Backround_ below\). The first element of **-index** is used to seach for an item of the group. The option **-start** always points to the beginning of the group, even if a position within the group is given. Returned indices are the first element of the striding group\(s\) that is/are being indicated. The list length must be a multiple of **grpSize**, which in turn must be at least 2. # Conceptual Backround ## Striding equivalent to first level of nested lists The striding within the list is seen as the first level of list nesting. E.g. **Nested list**: set deep {{1 a A} {2 b B} {3 c C}} **Flat strided list**: set flat {1 a A 2 b B 3 c C} Functions should operate the same way on both representation, with the only difference, that **-stride 3** must be specified in the second case. Unfortunately, the current implementation of **lsort** is not doing this. It interpretes **-index ""** as **-index 0**: % lsort -stride 2 {A 1 A 2 A 0} A 1 A 2 A 0 % lsort -stride 2 -index "" {B 2 B 1 A 3} A 3 B 2 B 1 ## Numeric position indices Numerical positional indices \(-start parameter, return value\) follow the flattened list and not the grouped list. This is different to the nested list view. Furthermore, if option **-subindices** is given and a non-empty argument for **-index**, then the group-start and index-into-group are added up. This gives compatibility with lindex, as in the no-stride case. # Examples In these examples, the variable _kvlist_ holds the key-value list: set kvlist {K1 V1 K2 V1 K1 K1} Example 1: find keys even if they exist multiple times: % lsearch -all -stride 2 -index 0 -exact $kvlist K1 0 4 Example 2: find existance of a value: % lsearch -all -stride 2 -index 1 -exact $kvlist V1 0 2 Remark that the indexes of the first group elements are returned. The real values are at "result\+index" eq **1 3**. Example 3: extract a sub-kv-list starting from key K2: % lrange $kvlist [lsearch -stride 2 -index 0 -exact $kvlist K2] end K2 V1 K1 K1 Example 4: find a group within a list: % lsearch -stride 2 -exact $kvlist {K2 V1} 2 Example 5: find in combined strided and nested list % lsearch -stride 2 -index {1 1} -exact\ {K0 {V0.0 V0.1} K1 {V1.0 V1.1}}\ V1.1 2 Example 6: subindices with strided list: % lsearch -stride 2 -index {1 1} -subindices {1 {a A} 2 {b B}} B 3 1 (that is: 2 for the group-start plus 1 for the intra-group index, and separately 1 for the further nested index. % lindex {1 {a A} 2 {b B}} 3 1 B to be consisten with: % lsearch -index {1 1} -subindices {{1 {a A}} {2 {b B}}} B 1 1 1 % lindex {{1 {a A}} {2 {b B}}} 1 1 1 B # Copyright This document has been placed in the public domain. |
Name change from tip/352.tip to tip/352.md.
|
| < | < | | | | | | | | > | | | | | | | | | 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 | # TIP 352: Tcl Style Guide Author: Ray Johnson <[email protected]> Author: Donal K. Fellows <[email protected]> Author: Mark Janssen <[email protected]> State: Draft Type: Informative Vote: Pending Created: 14-Jul-2009 Post-History: ----- # Abstract This document describes a set of conventions that it is suggested people use when writing Tcl code. It is substantially based on the Tcl/Tk Engineering Manual [[247]](247.md). ## NOTE _A transcription of the original version \(dated August 22, 1997\) of this file into PDF is available online at <http://www.tcl.tk/doc/styleGuide.pdf> - Donal K. Fellows._ # Introduction This is a manual for people who are developing Tcl code for Wish or any other Tcl application. It describes a set of conventions for writing code and the associated test scripts. There are three reasons for the conventions. First, the conventions ensure that certain important things get done; for example, every procedure must have documentation that describes each of its arguments and its result, and there must exist test scripts that exercise every line of code. Second, the conventions guarantee that all of the Tcl and Tk code has a uniform style. This makes it easier for us to use, read, and maintain each other's code. Third, the conventions help to avoid some common mistakes by prohibiting error-prone constructs such as building lists by hand instead of using the list building procedures. This document is based heavily on the _Tcl/Tk Engineering Manual_ written by John Ousterhout. John's engineering manual specified the style of the C code used in the implementation of Tcl/Tk and many of its extensions. The manual is very valuable to the development of Tcl/Tk and is an important reason why Tcl is a relatively easy system to maintain. Deciding any style standard involves making trade-offs that are usually subjective. This standard was created in an iterative process involving the |
︙ | ︙ | |||
64 65 66 67 68 69 70 | and how to write procedure headers. Section 5 desribes the Tcl naming conventions. Section 6 presents low-level coding conventions, such as how to indent and where to put curly braces. Section 7 contains a collection of rules and suggestions for writing comments. Section 8 describes how to write and maintain test suites. Section 9 contains a few miscellaneous topics, such as keeping a change log. | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | < > | | | | | | | | | | | | | | | | | | | | | | < > | | < > | | | | | | | | < > | 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 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 | and how to write procedure headers. Section 5 desribes the Tcl naming conventions. Section 6 presents low-level coding conventions, such as how to indent and where to put curly braces. Section 7 contains a collection of rules and suggestions for writing comments. Section 8 describes how to write and maintain test suites. Section 9 contains a few miscellaneous topics, such as keeping a change log. # Executable files An executable is a file, collection of files, or some other collection of Tcl code and necessary runtime environment. Often referred to as applications, an executable is simply what you run to start your program. The format and exact make up of an executable is platform-specific. At some point, however, a Tcl _start-up script_ will be evaluated. It is the start-up script that will bootstrap any Tcl based application. The role of the start-up script is to load any needed _packages_, set up any non-package specific state, and finally start the Tcl application by calling routines inside a Tcl package. If the start-up script is more than a few lines it should probably be a package itself. There are several ways to create executable scripts. Each major platform usually has a unique way of creating an executable application. Here is a brief description of how these applications should be created on each platform: 1. The most common method for creating executable applications on UNIX platforms is the infamous **\#!** mechanism built into most shells. Unfortunately, the most common approach of just giving a path to wish is not recommended. Don't do: #! /usr/local/tclsh8.0 -f "$0" "$@" > This method will not work if the file **tclsh** is another script that, for example, locates and starts the most recent version of Tcl. It also requires **tclsh** to be in a particular place, which makes the script less portable. Instead, the following method should be used which calls **/bin/sh** which will in turn exec the **wish** application. #!/bin/sh # the next line restarts using wish \ exec wish8.0 "$0" "$@" > This example will actually locate the **wish** application in the user's path which can be very useful for developers. The backslash is recognized as part of a comment to _sh_, but in Tcl the backslash continues the comment into the next line which keeps the _exec_ command from executing again. However, more stable sites would probably want to include the full path instead of just **wish**. Note that the version number of the **tclsh** or **wish** interpreter is usually added to the end of the program name. This allows you use a specific version of Tcl. In addition, many sites include a link of **wish** to the latest version currently installed. This is useful if you know that your code will work on any version of Tcl. 2. On the Windows platform you only need to end a file with the **.tcl** extension and the file will be run when the user double clicks on the file. This is, of course, assuming you have installed Tcl/Tk. > Alternatively, you may create a **.bat** file which explicitly executes **tclsh** or **wish** with an absolute path to your start-up script. Please check the Windows documentation for more details about **.bat** files. 3. The Macintosh platform doesn't really have a notion of an executable Tcl file. One of the reasons for this is that, unlike UNIX or Windows, you can only run one instance of an application at a time. So instead of callingwish with a specific script to load, we must create a copy of the **wish** application that is tied to our script. > The easiest way to do this is to use the application _Drag&Drop Tclets_ or the _SpecTcl_ GUI builder which can do this work for you. You can also do this by hand by putting the start-up script into a TEXT resource and name it _tclshrc_ - which ensures it gets sourced on start-up. This can be done with _ResEdit_ \(a tool provided by Apple\) or other tools that manipulate resources. Additional scripts can also be placed in TEXT resource to make the application completely contained. # Packages and namespaces Tcl applications consist of collections of _packages_. Each package provides code to implement a related set of features. For example, Tcl itself is a package, as is Tk; these packages happen to be implemented in both C and Tcl. Other packages are implemented completely in Tcl such as the **http** package included in the Tcl distribution. Packages are the units in which code is developed and distributed: a single package is typically developed by a single person or group and distributed as a unit. It is possible to combine many independently-developed packages into a single application; packages should be designed with this in mind. The notion of _namespaces_ were created to help make this easier. Namespaces help to hide private aspects of packages and avoid name collisions. A package will generally export one public namespace which will include all state and routines that are associated with the package. A package should not contain any global variables or global procedures. Side effects when loading a package should be avoided. This document will focus on packages written entirely in Tcl. For a discussion of packages built in C or C and Tcl see the _Tcl/Tk Engineering Manual_. ## Package names Each package should have a unique _name_. The name of the package is used to identify the package. It is also used as the name of the namespace that the package exports. It is best to have a simple one word name in all lower-case like **http**. Multi-word names are ok as well. Additional words should just be concatenated with the first word but start with a capital letter like **specMenu**. Coming up with a unique name for your package requires a collaborative component. For internal projects this is an easy task and can usually be decided among the management or principal engineers in your organization. For packages you wish to publish, however, you should make an effort to make sure that an existing package isn't already using the same name you are. This can often be done by checking the comp.lang.tcl newsgroup or the standard Tcl ftp sites. It is also suggested \(but not required\) that you register your name on the NIST Identifier Collaboration Service \(NICS\). It is located at: <http://pitch.nist.gov/nics> ## Version numbers Each package has a two-part version number such as 7.4. The first number \(7\) is called the major version number and the second \(4\) is called the minor version number. The version number changes with each public release of the package. If a new release contains only bug fixes, new features, and other upwardly compatible changes, so that code and scripts that worked with the old version will also work with the new version, then the minor version number increments and the major version number stays the same \(e.g., from 7.4 to 7.5\). If the new release contains substantial incompatibilities, so that existing code and scripts will have to be modified to run with the new version, then the major version number increments and the minor version number resets to zero \(e.g., from 7.4 to 8.0\). ## Package namespaces As of version 8.0, Tcl supports namespaces to hide the internal structure of a package. This helps avoid name collisions and provides a simpler way to manage packages. All packages written for Tcl 8.0 or newer should use namespaces. The name of the name space should be the same as the package name. ## Structure There are a couple of ways to deploy a package of Tcl commands. * A **pkgIndex.tcl** file is used to create _packages_ that can be loaded on demand by any Tcl script. Like a **tclIndex** file, a package specifies a set of Tcl and/or shared libraries that can be loaded when needed. A package, however, must be explicitly requested by using the **package require** command. You can use the **pkg\_mkIndex** command to create a package index file for your use. In most cases, particularly in code you distribute to others, it is better to use a package instead of the **tclIndex** auto-loading mechanism. * On the Macintosh platform, shared libraries can be made into self contained packages. You simply need to add a TEXT resource with the name of **pkgIndex**. It will be treated in the exact same fashion as a **pkgIndex.tcl** file. The **pkgIndex** resource should have the same format as the **pkgIndex.tcl** file. # How to organize a code file Each source code file should either contain an entire application or a set of related procedures that make up a package or a another type of identifiable module, such as the implementation of the menus for your application, or a set of procedures to implement HTTP access. Before writing any code you should think carefully about what functions are to be provided and divide them into files in a logical way. The most manageable size for files is usually in the range of 500-2000 lines. If a file gets much larger than this, it will be hard to remember everything that the file does. If a file is much shorter than this, then you may end up with too many files in a directory, which is also hard to manage. ## The file header The first part of a code file is referred to as the _header_. It contains overall information that is relevant throughout the file. It consists of everything but the definitions of the file's procedures. The header typically has four parts, as shown below: / # specMenu.tcl -- | # Abstract | # This file implements the Tcl code for creating and | # managing the menus in the SpecTcl application. \ # / # Copyright (c) 1994-1997 Sun Microsystems, Inc. | # Copyright | # See the file "license.terms" for information on usage and | # redistribution of this file, and for a DISCLAIMER OF ALL \ # WARRANTIES. # Revision # SCCS: %Z% %M% %I% %E% %U% String # RCS: Id / package require specTable Package | package provide specMenu 1.0 Definition | namespace eval specMenu { | namespace export addMenu | array set menuData {one two three} | ... \ } Abstract: The first few lines give the name of the file and a brief description of the overall functions provided by the file, just as in header files. Copyright notice: The notice protects ownership of the file. The copyright shown above is included in the Tcl and Tk sources. More product specific packages would probably have the words _All rights reserved included_ instead. If more than one entity contributed to the page they should each have a distinct copyright line. Revision string: The contents of this string are managed automatically by the source code control system for the file, such as RCS or SCCS \(both are shown in the example\). It identifies the file's current revision, date of last modification, and so on. Package definition: Also any **require** statements for other packages that this package depends on should be the first code in the file. Any global variables that are managed by this file should be declared at the top of the page. The name space definition should be next and the export list should be the first item in the namespace definition. Please structure your header pages in exactly the order given above and follow the syntax of the example as closely as possible. The file **fileHead.tcl** [_not available_] provides a template for a header page. ## Multi-file packages Some packages may be too large to fit into one file. You may want to consider breaking the package into multiple independent packages. However, when that is not an option you need to make one of the files the _primary_ file. The primary file will include the complete export list and the definitions of all exported variables and procedures. The secondary files should only contain supporting routines to the primary file. It is important to construct your package in this manner or utilities like **pkg\_mkIndex** will not work correctly. Finally, the header to the various files should make it clear which file is the primary file and which are supporting files. ## Procedure headers After the header you will have one or more procedures. Each procedure will begin with a _procedure header_ that gives overall documentation for the procedure, followed by the declaration and body for the procedure. See below for an example. # tcl::HistRedo -- # # Fetch the previous or specified event, execute it, and then # replace the current history item with that event. # # Arguments: # event (optional) index of history item to redo. Defaults # to -1, which means the previous event. # Results: # The result is that of the command being redone. Also replaces # the current history list item with the one being redone. proc tcl::HistRedo {{event -1}} { ... } The header should contain everything that a caller of the procedure needs to know in order to use the procedure, and nothing else. It consists of three parts: Abstract: The first lines in the header give the procedure's name, followed by a brief description of what the procedure does. This should not be a |
︙ | ︙ | |||
334 335 336 337 338 339 340 | comment should describe the expected type and describe it's function. Optional arguments should be pointed out and the default behavior of an unspecified argument should be mentioned. Comments for all of the arguments should line up on the same tab stop. Results: The last part of the header describes the value returned by the procedure. The type and the intended use of the result should be | | | | | | | | | | | | | | | | | | < > | | | | | | | | | | | | | | | | | | | | | | | | | | | < | > | | | | | | | | | < | > | | | | | | | | | | | < > | | | | | | | | < < | > > | | | | | | | | < > | | | | | | | | | | | | | < < | > > | | | | | < < | > > | | | | | | | | < > | | < > | | < < | > > | | | | | | | | | < | > | | | | | | | | | | | | | | < > | | | < > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 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 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 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 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 1014 | comment should describe the expected type and describe it's function. Optional arguments should be pointed out and the default behavior of an unspecified argument should be mentioned. Comments for all of the arguments should line up on the same tab stop. Results: The last part of the header describes the value returned by the procedure. The type and the intended use of the result should be described. This section should also mention any _side effects_ that are worth noting. The file **tclProcHead** [_not available_] contains a template for a procedure header which should be used as a base for all new Tcl commands. Follow the syntax of the above example exactly \(same indentation, double-dash after the procedure name, etc.\). ## Procedure declarations The procedure declaration should also follow exactly the syntax in the example above. Note that the procedure is defined outside the namespace command that defines the export list and namespace globals. The first line gives the **proc** keyword, the procedure name, and an argument list. If there are many arguments, they may spill onto additional lines \(see Sections 6.1 and 6.3 for information about indentation\). ## Parameter order Procedure parameters may be divided into three categories. _In_ parameters only pass information into the procedure \(either directly or by pointing to information that the procedure reads\). _Out_ parameters point to things in the caller's memory that the procedure modifies such as the name of a variable the procedure will modify. _In-out_ parameters do both. Below is a set of rules for deciding on the order of parameters to a procedure: 1. Parameters should normally appear in the order in, in/out, out, except where overridden by the rules below. 2. If an argument is actually a sub-command for the command than it should be the first argument of the command. For example: proc graph::tree {subCmd args} { switch $subCmd { add { eval add_node $args } draw {... 3. If there is a group of procedures, all of which operate on an argument of a particular type, such as a file path or widget path, the argument should be the first argument to each of the procedures \(or after the sub-command argument\). ## Procedure bodies The body of a procedure follows the declaration. See Section 6 for the coding conventions that govern procedure bodies. The curly braces enclosing the body should be on different lines, as shown in the examples above, even if the body of the procedure is empty. # Naming conventions Choosing names is one of the most important aspects of programming. Good names clarify the function of a program and reduce the need for other documentation. Poor names result in ambiguity, confusion, and error. This section gives some general principles to follow when choosing names and lists specific rules for name syntax, such as capitalization. ## General considerations The ideal variable name is one that instantly conveys as much information as possible about the purpose of the variable it refers to. When choosing names, play devil's advocate with yourself to see if there are ways that a name might be misinterpreted or confused. Here are some things to consider: 1. Are you consistent? Use the same name to refer to the same thing everywhere. For example, within the code for handling standard bindings in Tk widgets, a standard name **w** is always used to refer to the window associated with the current event. 2. If someone sees the name out of context, will they realize what it stands for, or could they confuse it with something else? For example, the procedure name **buildStructure** could get confused with some other part of the system. A name like **buildGraphNode** both describes what part of the system it belongs to and what it is probably used for. 3. Could this name be confused with some other name? For example, it's probably a mistake to have two variables **str** and **string** in the same procedure: it will be hard for anyone to remember which is which. Instead, change the names to reflect their functions. For example, if the strings are used as source and destination for a copy operation, name them **src** and **dst**. 4. Is the name so generic that it doesn't convey any information? The variable **str** from the previous paragraph is an example of this; changing its name to **src** makes the name less generic and hence conveys more information. ## Basic syntax rules Below are some specific rules governing the syntax of names. Please follow the rules exactly, since they make it possible to determine certain properties of a variable just from its name. 1. Exported names for both procedures and variables always start with a _lower_-case letter. Procedures and variables that are meant only for use with in the current package or namespace should start with an _upper_-case letter. We chose lower-case for the exported symbols because it is possible they may be commonly used from the command line and they should be easy to write. For example: # CountNum is a private variable set CountNum 0 # The function addWindow is public proc addWindow {} {... # newWindow is a public interface in the spectcl namespace proc spectcl::newWindow {} {... 2. In multi-word names, the first letter of each trailing word is capitalized. Do not use underscores or dashes as separators between the words of a name. set numWindows 0 3. Any variable whose value refers to another variable has a name that ends in **Name**. Furthermore, the name should also indicate what type of variable the name is referring to. These names are often used in arguments to procedures that are taking a name of a variable. proc foo::Bar {arrayName} { upvar 1 $arrayName array ... } 4. Variables that hold Tcl code that will be **eval**ed should have names ending in **Script**. proc log::eval {logScript} { if {$Log::logOn} { set result [catch {eval $logScript} msg] ... 5. Variables that hold a partial Tcl command that must have additional arguments appended before being a valid script should have names ending in **Cmd**. foreach scrollCmd $listScrollCmds { eval $scrollCmd $args } # Low-level coding conventions This section describes several low-level syntactic rules for writing Tcl code. These rules help to ensure that all of the Tcl code looks the same, and they prohibit a few confusing coding constructs. ## Indents are 4 spaces Each level of indentation should be four spaces. There are ways to set 4-space indents in all of the most common editors. Be sure that your editor really uses four spaces for the indent, rather than just displaying tabs as four spaces wide; if you use the latter approach then the indents will appear eight spaces wide in other editors. ## Code comments occupy full lines Comments that document code should occupy full lines, rather than being tacked onto the ends of lines containing code. The reason for this is that side-by-side comments are hard to see, particularly if neighboring statements are long enough to overlap the side-by-side comments. Also it is easy to place comments in a place that could cause errors. Comments must have exactly the structure shown in the example below, with a blank line above and below the comment. The leading blank line can be omitted if the comment is at the beginning of a block, as is the case in the second comment in the example below. Each comment should be indented to the same level as the surrounding code. Use proper English in comments: write complete sentences, capitalize the first word of each sentence, and so on. # If we are running on the Macintosh platform then we can # assume that the sources are located in the resource fork # of our application, and we do not need to search for them. # Note that there is a blank line below it to separate it # more strongly from the code. if {$tcl_platform(platform) == "macintosh"} { return } foreach dir $dirList { # If the source succeds then we are done. # Note there is no blank line above the comment; # the indentation change is visible enough. if {![catch {source [file join $dir file.tcl]}]} { break } } ## Continuation lines are indented 8 spaces You should use continuation lines to make sure that no single line exceeds 80 characters in length. Continuation lines should be indented 8 spaces so that they won't be confused with an immediately-following nested block. Pick clean places to break your lines for continuation, so that the continuation doesn't obscure the structure of the statement. For example, if a procedure call requires continuation lines, try to avoid situations where a single argument spans multiple lines. If the test for an **if** or **while** command spans lines, try to make each line have the same nesting level of parentheses and/or brackets if possible. I try to start each continuation line with an operator such as **\***, **&&**, or **\|\|**; this makes it clear that the line is a continuation, since a new statement would never start with such an operator. ## Only one command per line You should only have one Tcl command per line on the page. Do not use the semi-colon character to place multiple commands on the same line. This makes the code easier to read and helps with debugging. ## Curly braces: \{ goes at the end of a line Open curly braces can not appear on lines by themselves in Tcl. Instead, they should be placed at the end of the preceding line. Close curly braces are indented to the same level as the outer code, i.e., four spaces less than the statements they enclose. However, you shouldalways use curly braces rather than some other list generating mechanism that will work in the Tcl language. This will help make code more readable, will avoid unwanted side effects, and in many cases will generate faster code with the Tcl compiler. Control structures should always use curly braces, even if there is only one statement in the block. Thus you shouldn't write code like if {$tcl_platform(platform) == "unix"} return but rather if {$tcl_platform(platform) == "unix"} { return } This approach makes code less dense, but it avoids potential mistakes like unwanted Tcl substitutions. It also makes it easier to set breakpoints in a debugger, since it guarantees that each statement is on a separate line and can be named individually. ## Parenthesize expressions Use parentheses around each subexpression in an expression to make it absolutely clear what is the evaluation order of the expression \(a reader of your code should not need to remember Tcl's precedence rules\). For example, don't type if {$x > 22 && $y <= 47} ... Instead, type this: if {($x > 22) && ($y <= 47)} ... ## Always use the return statement You should always explicitly use the **return** statement to return values from a Tcl procedure. By default Tcl will return the value of the last Tcl statement executed in a Tcl procedure as the return value of the procedure which often leads to confusion as to where the result is coming from. In addition, you should use a **return** statement with no argument for procedures whose results are ignored. Supplying this return will actually speed up your application with the new Tcl compiler. For example, don't write code like this: proc foo {x y} { if {$x < 0} { incr x } else { expr $x + $y } } But rather, type this: proc foo {x y} { if {$x < 0} { return [incr x] } else { return [expr $x + $y] } } For Tcl procedures that have no return value a single **return** statement with no arguments is placed at the end of the procedure. ## Switch statements The **switch** statement should be formatted as below. Always use the **--** option to avoid having the string be confused with an option. This can happen when the string is user generated. Comments can be added on the same line as the pattern to comment the pattern case. The comments for each case should line up on the same tab stop and must be within the braces. Note that this is an exception to the standard commenting conventions. switch -regexp -- $string { plus - add { # Do add task ... } subtract { # Do subtract case ... } default { ... } } ## If statements Never use the **then** word of an **if** statement. It is syntactic sugar that really isn't that useful. However, the **else** word should always be used as it does impart some semantic information and it is more like the C language. Here is an example: if {$x < 0} { ... } elseif {$x == 0} { ... } else { ... } # Documenting code The purpose of documentation is to save time and reduce errors. Documentation is typically used for two purposes. First, people will read the documentation to find out how to use your code. For example, they will read procedure headers to learn how to call the procedures. Ideally, people should have to learn as little as possible about your code in order to use it correctly. Second, people will read the documentation to find out how your code works internally, so they can fix bugs or add new features; again, good documentation will allow them to make their fixes or enhancements while learning the minimum possible about your code. More documentation isn't necessarily better: wading through pages of documentation may not be any easier than deciphering the code. Try to pick out the most important things that will help people to understand your code and focus on these in your documentation. ## Document things with wide impact The most important things to document are those that affect many different pieces of a program. Thus it is essential that every procedure interface, every structure declaration, and every global variable be documented clearly. If you haven't documented one of these things it will be necessary to look at all the uses of the thing to figure out how it's supposed to work; this will be time-consuming and error-prone. On the other hand, things with only local impact may not need much documentation. For example, in short procedures I don't usually have comments explaining the local variables. If the overall function of the procedure has been explained, and if there isn't much code in the procedure, and if the variables have meaningful names, then it will be easy to figure out how they are used. On the other hand, for long procedures with many variables I usually document the key variables. Similarly, when I write short procedures I don't usually have any comments in the procedure's code: the procedure header provides enough information to figure out what is going on. For long procedures I place a comment block before each major piece of the procedure to clarify the overall flow through the procedure. ## Don't just repeat what's in the code The most common mistake I see in documentation \(besides it not being there at all\) is that it repeats what is already obvious from the code, such as this trivial \(but exasperatingly common\) example: # Increment i. incr i Documentation should provide higher-level information about the overall function of the code, helping readers to understand what a complex collection of statements really means. For example, the comment # Probe into the array to see if the symbol exists. is likely to be much more helpful than # Loop through every array index, get the third value of the # list in the content to determine if it has the symbol we are # looking for. Set the result to the symbol if we find it. Everything in this second comment is probably obvious from the code that follows it. Another thing to consider in your comments is word choice. Use different words in the comments than the words that appear in variable or procedure names. For example, the comment # SwapPanels -- # # Swap the panels. # ... is not a very useful comment. Everything in the comment is already obvious from the procedure's name. Here is a much more useful comment: # SwapPanels -- # # Unmap the current UI panel from the parent frame and replace # it with the newly specified frame. Make sure that the new # panel fits into the old frame and resize if needed. # ... This comment tells _why_ you might want to use the procedure, in addition to _what_ it does, which makes the comment much more useful. ## Document each thing in exactly one place Systems evolve over time. If something is documented in several places, it will be hard to keep the documentation up to date as the system changes. Instead, try to document each major design decision in exactly one place, as near as possible to the code that implements the design decision. The principal documentation for each procedure goes in the procedure header. There's no need to repeat this information again in the body of the procedure \(but you might have additional comments in the procedure body to fill in details not described in the procedure header\). If a library procedure is documented thoroughly in a manual entry, then I may make the header for the procedure very terse, simply referring to the manual entry. The other side of this coin is that every major design decision needs to be documented _at least_ once. If a design decision is used in many places, it may be hard to pick a central place to document it. Try to find a data structure or key procedure where you can place the main body of comments; then reference this body in the other places where the decision is used. If all else fails, add a block of comments to the header page of one of the files implementing the decision. ## Write clean code The best way to produce a well-documented system is to write clean and simple code. This way there won't be much to document. If code is clean, it means that there are a few simple ideas that explain its operation; all you have to do is to document those key ideas. When writing code, ask yourself if there is a simple concept behind the code. If not, perhaps you should rethink the code. If it takes a lot of documentation to explain a piece of code, it is a sign that you haven't found a clean solution to the problem. ## Document as you go It is extremely important to write the documentation as you write the code. It's very tempting to put off the documentation until the end; after all, the code will change, so why waste time writing documentation now when you'll have to change it later? The problem is that the end never comes - there is always more code to write. Also, the more undocumented code that you accumulate, the harder it is to work up the energy to document it. So, you just write more undocumented code. I've seen many people start a project fully intending to go back at the end and write all the documentation, but I've never seen anyone actually do it. If you do the documentation as you go, it won't add much to your coding time and you won't have to worry about doing it later. Also, the best time to document code is when the key ideas are fresh in your mind, which is when you're first writing the code. When I write new code, I write all of the header comments for a group of procedures before I fill in any of the bodies of the procedures. This way I can think about the overall structure and how the pieces fit together before getting bogged down in the details of individual procedures. ## Document tricky situations If code is non-obvious, meaning that its structure and correctness depend on information that won't be obvious to someone reading it for the first time, be sure to document the non-obvious information. One good indicator of a tricky situation is a bug. If you discover a subtle property of your program while fixing a bug, be sure to add a comment explaining the problem and its solution. Of course, it's even better if you can fix the bug in a way that eliminates the subtle behavior, but this isn't always possible. # Testing One of the environments where Tcl works best is for testing. While Tcl has traditionally been used for testing C code it is equally as good at testing other Tcl code. Whenever you write new code you should write Tcl test scripts to go with that code and save the tests in files so that they can be re-run later. Writing test scripts isn't as tedious as it may sound. If you're developing your code carefully you're already doing a lot of testing; all you need to do is type your test cases into a script file where they can be reused, rather than typing them interactively where they vanish after they're run. ## Basics Tests should be organized into script files, where each file contains a collection of related tests. Individual tests should be based on the procedure **test**, just like in the Tcl and Tk test suites. Here are two examples: test expr-3.1 {floating-point operators} { expr 2.3*.6 } 1.38 test expr-3.2 {floating-point operators} {unixOnly} { list [catch {expr 2.3/0} msg] $msg } {1 {divide by zero}} **test** is a procedure defined in a script file named **defs**, which is **source**d by each test file. **test** takes four or five arguments: a test identifier, a string describing the test, an optional argument describing the conditions under which this test should run, a test script, and the expected result of the script. **test** evaluates the script and checks to be sure that it produces the expected result. If not, it prints a message like the following: ==== expr-3.1 floating-point operators ==== Contents of test case: expr 2.3*.6 ==== Result was: 1.39 ---- Result should have been: 1.38 ---- expr-3.1 FAILED To run a set of tests, you start up the application and **source** a test file. If all goes well no messages appear; if errors are detected, a message is printed for each error. The test identifier, such as **expr-3.1**, is printed when errors occur. It can be used to search a test script to locate the source for a failed test. The first part of the identifier, such as **expr**, should be the same as the name of the test file, except that the test file should have a **.test** extension, such as **expr.test**. The two numbers allow you to divide your tests into groups. The tests in a particular group \(e.g., all the **expr-3.**_n_ tests\) relate to a single sub-feature, such as a single procedure. The tests should appear in the test file in the same order as their numbers. The test name, such as **floating-point operators**, is printed when errors occur. It provides human-readable information about the general nature of the test. Before writing tests I suggest that you look over some of the test files for Tcl and Tk to see how they are structured. You may also want to look at the **README** files in the Tcl and Tk test directories to learn about additional features that provide more verbose output or restrict the set of tests that are run. ## Organizing tests Organize your tests to match the code being tested. The best way to do this is to have one test file for each source code file, with the name of the test file derived from the name of the source file in an obvious way \(e.g. **http.test** contains tests for the code in **http.tcl**\). Within the test file, have one group of tests for each procedure \(for example, all the **http-3.**_n_ tests in **http.test** are for the procedure **http::geturl**\). The order of the tests within a group should be the same as the order of the code within the procedure. This approach makes it easy to find the tests for a particular piece of code and add new tests as the code changes. The Tcl test suite was written a long time ago and uses a different style where there is one file for each Tcl command or group of related commands, and the tests are grouped within the file by sub-command or features. In this approach the relationship between tests and particular pieces of code is much less obvious, so it is harder to maintain the tests as the code evolves. I don't recommend using this approach for new tests. ## Coverage When writing tests, you should attempt to exercise every line of source code at least once. There will be occasionally be code that you can't exercise, such as code that exits the application, but situations like this are rare. You may find it hard to exercise some pieces of code because existing Tcl commands don't provide fine enough control to generate all the possible execution paths. In situations like this, write one or more new Tcl commands just for testing purposes. It's much better to test a facility directly then to rely on some side effect for testing that may change over time. Use a similar approach in your own code, where you have an extra file with additional commands for testing. It's not sufficient just to make sure each line of code is executed by your tests. In addition, your tests must discriminate between code that executes correctly and code that isn't correct. For example, write tests to make sure that the **then** and **else** branches of each **if** statement are taken under the correct conditions. For a loop, run different tests to make the loop execute zero times, one time, and two or more times. If a piece of code removes an element from a list, try cases where the element to be removed is the first element, last element, only element, and neither first element nor last. Try to find all the places where different pieces of code interact in unusual ways, and exercise the different possible interactions. ## Fixing bugs Whenever you find a bug in your code it means that the test suite wasn't complete. As part of fixing the bug, you should add new tests that detect the presence of the bug. I recommend writing the tests after you've located the bug but _before_ you fix it. That way you can verify that the bug happens before you implement the fix and the bug doesn't happen afterwards, so you'll know you've really fixed something. Use bugs to refine your testing approach: think about what you might be able to do differently when you write tests in the future to keep bugs like this one from going undetected. ## Tricky features I also use tests as a way of illustrating the need for tricky code. If a piece of code has an unusual structure, and particularly if the code is hard to explain, I try to write additional tests that will fail if the code is implemented in the obvious manner instead of using the tricky approach. This way, if someone comes along later, doesn't understand the documentation for the code, decides the complex structure is unnecessary, and changes the code back to the simple \(but incorrect\) form, the test will fail and the person will be able to use the test to understand why the code needs to be the way it is. Illustrative tests are not a substitute for good documentation, but they provide a useful addition. ## Test independence Try to make tests independent of each other, so that each test can be understood in isolation. For example, one test shouldn't depend on commands executed in a previous test. This is important because the test suite allows tests to be run selectively: if the tests depend on each other, then false errors will be reported when someone runs a few of the tests without the others. For convenience, you may execute a few statements in the test file to set up a test configuration and then run several tests based on that configuration. If you do this, put the setup code outside the calls to thetest procedure so it will always run even if the individual tests aren't run. I suggest keeping a very simple structure consisting of setup followed by a group of tests. Don't perform some setup, run a few tests, modify the setup slightly, run a few more tests, modify the setup again, and so on. If you do this, it will be hard for people to figure out what the setup is at any given point and when they add tests later they are likely to break the setup. # Miscellaneous ## Porting issues Writing portable scripts in Tcl is actually quite easy as Tcl itself is quite portable. However, issues do arise that may require writing platform specific code. To conditionalize your code in this manner you should use the **tcl\_platform** array to determine platform specific differences. You should avoid the use of theenv variable unless you have already determined the platform you are running on via the **tcl\_platform** array. As Tcl/Tk has become more cross platform we have added commands that aid in making your code more portable. The most common porting mistakes result from assumptions about file names and locations. To avoid such mistakes always use the **file join** command and list commands so that you will handle different file separation characters or spaces in file names. In Tk, you should always use provided high level dialog boxes instead or creating your own. The **font** and **menu** commands has also be revamped to make writing cross-platform code easier. ## Changes files Each package should contain a file namedchanges that keeps a log of all significant changes made to the package. The **changes** file provides a way for users to find out what's new in each new release, what bugs have been fixed, and what compatibility problems might be intro- duced by the new release. The **changes** file should be in chronological order. Just add short blurbs to it each time you make a change. Here is a sample from the Tk **changes** file: 5/19/94 (bug fix) Canvases didn't generate proper Postscript for stippled text. (RJ) 5/20/94 (new feature) Added "bell" command to ring the display's bell. (JO) 5/26/94 (feature removed) Removed support for "fill" justify mode from Tk_GetJustify and from the TK_CONFIG_JUSTIFY configuration option. None of the built-in widgets ever supported this mode anyway. (SS) *** POTENTIAL INCOMPATIBILITY *** The entries in the **changes** file can be relatively terse; once someone finds a change that is relevant, they can always go to the manual entries or code to find out more about it. Be sure to highlight changes that cause compatibility problems, so people can scan the **changes** file quickly to locate the incompatibilities. Also be sure to add your initials to the entry so that people scanning the log will know who made a particular change. _\(The Tcl and Tk core additionally uses a ChangeLog file that has a much higher detail within it. This has the advantage of having more tooling support, but tends to be so verbose that the shorter summaries in the changes file are still written up by the core maintainers before each release.\)_ # Copyright The original version of this document is copyright \(C\) 1997 Sun Microsystems, Inc. Revisions to reflect current community best-practice are public domain. |
Name change from tip/353.tip to tip/353.md.
|
| < | < | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | < > | | | | | | | | | | | < > | | | | | < > | | | > | 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 | # TIP 353: NR-enabled Expressions for Extensions Author: Don Porter <[email protected]> State: Final Type: Project Vote: Done Created: 29-Jul-2009 Tcl-Version: 8.6 Post-History: ----- # Abstract This TIP proposes the new public routine **Tcl\_NRExprObj** to provide extension commands that evaluate Tcl expressions the ability to do so in a non-recursive manner. # Background In a few contexts, expressions that contain **yield** raise the error "_cannot yield: C stack busy_"; see Tcl Bugs 2823282 <https://sourceforge.net/support/tracker.php?aid=2823282> and 2823276 <https://sourceforge.net/support/tracker.php?aid=2823276> . This is because a few little-visited corners of Tcl's implementation call the routine **Tcl\_ExprObj** and that routine is not NR-enabled. For extensions wishing to evaluate Tcl expressions, **Tcl\_ExprObj** is not little-visited. It is the public, supported, recommended tool for the job. Just as [[322]](322.md) provided a routine **Tcl\_NREvalObj** as an NR-enabled replacement for **Tcl\_EvalObj**, extensions wishing to NR-enable their commands need an analogous replacement for **Tcl\_ExprObj**. # Rationale Tcl has a long history of providing extensions access to the same capabilities available to the built-in command set so that extension commands are on an equal footing, not in a second class status. Keeping with that, we want extensions to be able to create NR-enabled commands, so we need to provide an interface for extensions to evaluate expressions in an NR-enabled manner. This TIP can be seen as filling up a hole in [[322]](322.md). # Scope Limitations The Tcl public C interface provides a whole family of variants of **Tcl\_ExprObj**: **Tcl\_ExprLongObj**, **Tcl\_ExprDoubleObj**, **Tcl\_ExprBooleanObj**, **Tcl\_ExprLong**, **Tcl\_ExprDouble**, **Tcl\_ExprBoolean**, **Tcl\_ExprString**. NR-enabled counterparts to these routines are _not_ proposed. Extensions rewriting their command procedures to use the proposed **Tcl\_NRExprObj** for sake of NR-enabling can at the same time be expected to convert from these convenience wrappers to more direct use of a single NR-enabled primitive. # Proposal Add the following routine to Tcl's public interface: > int **Tcl\_NRExprObj**\(Tcl\_Interp \*_interp_, Tcl\_Obj \*_objPtr_, Tcl\_Obj \*_resultPtr_\) This routine places on the NR stack a request that the Tcl non-recursive trampoline evaluate the _objPtr_ value as a Tcl expression in interpreter _interp_. This routine returns the value **TCL\_OK**, since there is \(currently\) no way this request operation can fail. The proposed interface still provides for an int return value so that future revisions to Tcl's internals have the freedom to change that without need to change the public interface. The _resultPtr_ argument must be an unshared Tcl value. When expression evaluation succeeds, the result of the expression is written to _resultPtr_ in the same way that **Tcl\_SetStringObj** would write a string value to an unshared Tcl value. If expression evaluation produces any return code other than **TCL\_OK**, the value of _resultPtr_ is left untouched. Callers of **Tcl\_NRExprObj** will also need to call **Tcl\_NRAddCallback** to request a **Tcl\_NRPostProc** callback routine be placed on the NR stack which can take care of managing _resultPtr_ as appropriate depending on the _result_ value. # Implementation The patch attached to Tcl Bug 2823282 <https://sourceforge.net/support/tracker.php?aid=2823282> implements this proposal. # Compatibility There should be no compatibility issues, since at the interface level this is just the addition of a new routine. Revisions to the internal implementations of existing routines should be harmless. # Migration As an example for extensions to follow, consider this template for a **Tcl\_ObjCmdProc** currently calling **Tcl\_ExprObj**. int ObjCmd(ClientData cd, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { int code; Tcl_Obj *resultPtr; /* determine expression, objPtr */ code = Tcl_ExprObj(interp, objPtr, &resultPtr); if (code != TCL_OK) {return code} /* resultPtr holds expression result; continue */ } Tcl_CreateObjCommand(interp, name, ObjCmd, /* ... */); To use **Tcl\_NRExprObj** to NR-enable this command, rewrite along these lines: int ObjCmd(ClientData cd, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { return Tcl_NRCallObjProc(interp, NRObjCmd, cd, objc, objv); } int NRObjCmd(ClientData cd, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { Tcl_Obj *resultPtr = Tcl_NewObj(); /* determine expression, objPtr */ Tcl_NRAddCallback(interp, Callback, resultPtr, /*...*/); return Tcl_NRExprObj(interp, objPtr, resultPtr); } int Callback(ClientData data[], Tcl_Interp *interp, int code) { Tcl_Obj *resultPtr = data[0]; if (code != TCL_OK) {Tcl_DecrRefCount(resultPtr); return code;} /* resultPtr holds expression result; continue */ } Tcl_NRCreateCommand(interp, name, ObjCmd, NRObjCmd, /*...*/); # Copyright This document has been placed in the public domain. |
Name change from tip/354.tip to tip/354.md.
|
| < | | | | | | < | | > | | | | | | | | | | | | | | | | > | 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 | # TIP 354: Minor Production-Driven TclOO Revisions State: Final Type: Project Tcl-Version: 8.6 Vote: Done Post-History: Author: Donal K. Fellows <[email protected]> Created: 26-Aug-2009 ----- # Abstract This TIP describes a few small changes required for solving issues that have been found when using TclOO in production. # Description TclOO \(see [[257]](257.md)\) has now had a substantial amount of use for relatively complex functionality \(as well as production deployment\) and it has turned out that there were a few small changes required. 1. The scope of resolution for the target of a **forward**ed method is updated so that it is with respect to the object's namespace. This means that a class may create methods that forward to a command given by each instance, which makes creating megawidgets by wrapping real Tk widgets much easier, since the forwards do not have to be created at the instance level. 2. A subcommand was added to **info object** to allow the discovery of the namespace of an object by code outside that object. This makes it far easier for code that needs to "break the abstraction" to do so, which turns out to be necessary for things like serialization. This subcommand, **namespace**, takes an object name as its only argument and returns the name of the object's namespace. > To expand on the requirements for serialization, the serialization code needs to call a method on each object to create the serialization for that object. However, the method should not be part of the public API for the object as it cannot perform a complete serialization correctly, since the serialization depends on the rest of the object graph. \(It also requires a number of global overheads that are best applied once, not repeatedly.\) > Note that I plan to release the serialization code itself \(originally developed as part of a solution for a Rosetta Code task\) as a package via tcllib. This TIP does not propose its inclusion with Tcl. 3. A new C API function has been added to allow code at that level to _efficiently_ discover the name of an object that it already has a handle to. This new function, **Tcl\_GetObjectName**, returns a shared Tcl\_Obj reference to the name that needs no special reference count management. # Copyright This document has been placed in the public domain. |
Name change from tip/355.tip to tip/355.md.
|
| < | < | | | | | | | > | | | | | | | | | | | | | | | | | | > | 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 | # TIP 355: Stop Fast Recycling of Channel Names on Unix Author: Alexandre Ferrieux <[email protected]> State: Draft Type: Project Vote: Pending Created: 01-Sep-2009 Tcl-Version: 8.7 Post-History: ----- # Abstract This TIP proposes to put an end to the unix-specific habit of naming channels after the underlying file descriptor, by using a much longer-lived incremented counter instead. # Background Tcl \(non-reflected\) channel names are of the general form $_KIND_$_HANDLE_ on all OSes, $_KIND_ being something like "**file**", "**pipe**", etc, and $_HANDLE_ being the OS file descriptor or handle. This is clearly a cost-effective way of guaranteeing process-wide unicity at any given time. However, on unix, file descriptors are in a "compact table", i.e. they are small integers that are reused as quickly as possible, to keep the range small for efficiency reasons \(and also constraints like the select\(\) API\). And as witnessed by [Bug 2826430]<https://sourceforge.net/support/tracker.php?aid=2826430> , channel name recycling is dangerous. Quite possibly a bunch of applications running today get occasionally hit, with very hard to decipher symptoms, and an even harder to reproduce setup. # Proposed Change This TIP proposes to replace the file descriptor in unix channel names by an ever-increasing, process-unique counter. # Rationale This change would bring unix channels in line with the rest of the crowd, since Windows handles seem to have a very long cycle, and reflected channels already use a counter. It could even be more ambitious in that \(1\) even Windows channels use the counter instead of relying on the OS's lifetime guarantee, and \(2\) reflected channels use the same counter instead of their own. Choice left open for discussion. The implementation is trivial: a new public function, **Tcl\_GetProcessUniqueNum**, returns a global integer counter which is incremented under mutex. \(It will wrap at MAXINT and I am listening to whoever thinks it is still a problem...\). # Reference Implementation The patch attached to the aforementioned bug <https://sourceforge.net/support/tracker.php?aid=2826430> adds this stub entry, and updates all unix channel naming schemes to use it. # Copyright This document has been placed in the public domain. |
Name change from tip/356.tip to tip/356.md.
|
| < | < | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | < > | | | | | | | < > | | | | < > | | | | | | < > | | | > | 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 | # TIP 356: NR-enabled Substitutions for Extensions Author: Don Porter <[email protected]> State: Final Type: Project Vote: Done Created: 17-Sep-2009 Tcl-Version: 8.6 Post-History: Keywords: Tcl, C API, subst ----- # Abstract This TIP proposes the new public routine **Tcl\_NRSubstObj** to provide extension commands that evaluate Tcl substitutions the ability to do so in a non-recursive manner. # Background Continuing in the path of [[322]](322.md) and [[353]](353.md), we want extensions to be able to create NR-enabled commands, and any command procedures currently calling the **Tcl\_SubstObj** routine are not NR-enabled. The solution is to provide the NR-enabled counterpart. # Proposal Add the following routine to Tcl's public interface: > int **Tcl\_NRSubstObj**\(Tcl\_Interp \*_interp_, Tcl\_Obj \*_objPtr_, int _flags_\) This routine places on the NR stack a request that the Tcl non-recursive trampoline evaluate the _objPtr_ value as a Tcl substitution in interpreter _interp_, as controlled by the value of _flags_. The _flags_ value is the same combination of **TCL\_SUBST\_BACKSLASHES**, **TCL\_SUBST\_COMMANDS**, and **TCL\_SUBST\_VARIABLES** that control **Tcl\_SubstObj**. This routine returns the value **TCL\_OK**, since there is \(currently\) no way this request operation can fail. The proposed interface still provides for an int return value so that future revisions to Tcl's internals have the freedom to change that without need to change the public interface. After the trampoline completes the requested substitution, it will pass the return code, either **TCL\_OK** or **TCL\_ERROR**, to the next callback on the NR-stack, and either the result of the substitution or the error message will be stored in the result of _interp_. The caller of **Tcl\_NRSubstObj** may also call **Tcl\_NRAddCallback** to request a **Tcl\_NRPostProc** callback routine be placed on the NR stack to receive these results, if needed to achieve the task the caller is performing. # Implementation The proposed routine is already present in the HEAD of Tcl as the internal routine **TclNRSubstObj**. This proposal would simply promote it to Tcl's public interface. # Compatibility There should be no compatibility issues, since at the interface level this is just the addition of a new routine. # Migration As an example for extensions to follow, consider this template for a **Tcl\_ObjCmdProc** currently calling **Tcl\_SubstObj**. int ObjCmd(ClientData cd, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) Tcl_Obj *resultPtr; /* determine text to be substituted, objPtr */ /* determine flags value to control substitution */ resultPtr = Tcl_SubstObj(interp, objPtr, flags); if (resultPtr == NULL) {return TCL_ERROR} /* resultPtr holds substitution result; continue */ } Tcl_CreateObjCommand(interp, name, ObjCmd, /* ... */); To use **Tcl\_NRSubstObj** to NR-enable this command, rewrite along these lines: int ObjCmd(ClientData cd, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { return Tcl_NRCallObjProc(interp, NRObjCmd, cd, objc, objv); } int NRObjCmd(ClientData cd, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { /* determine text to be substituted, objPtr */ /* determine flags value to control substitution */ Tcl_NRAddCallback(interp, Callback, /*...*/); return Tcl_NRSubstObj(interp, objPtr, flags); } int Callback(ClientData data[], Tcl_Interp *interp, int code) { Tcl_Obj *resultPtr; if (code == TCL_ERROR) {return TCL_ERROR;} resultPtr = Tcl_GetObjResult(interp); /* resultPtr holds expression result; continue */ } Tcl_NRCreateCommand(interp, name, ObjCmd, NRObjCmd, /*...*/); # Copyright This document has been placed in the public domain. |
Name change from tip/357.tip to tip/357.md.
|
| < | < | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | < | | > | | | | | | | | > | 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 | # TIP 357: Export TclLoadFile Author: Kevin Kenny <[email protected]> State: Final Type: Project Vote: Done Created: 01-Oct-2009 Post-History: Tcl-Version: 8.6 ----- # Abstract This TIP proposes to promote the internal calls, _TclLoadFile_ and _TclpFindSymbol_ to the external API, making them available to C extensions. In addition, it proposes to introduce a _Tcl\_FSUnloadFile_ to the VFS layer, removing the weird duplicate client data from _TclLoadFile_ and wrapping all necessary data into the **Tcl\_LoadHandle** # Rationale In developing TDBC [[308]](308.md), the author of this TIP was advised to look at the way that the 'oratcl' extension contrives to build on a system where Oracle is not installed as a model for TDBC extensions. Examination of the code revealed that it operates essentially by constructing at run time a Stubs table for the routines in the Oracle client library. There is a maze of **\#if** directives selecting whether this process is accomplished by the system calls that manage Unix .so files \(_dlopen_ and friends\), Windows .DLL files \(_LoadLibrary_ and related calls\), HP-UX .shl files \(_shl\_load,_ etc.\), and so on. Tcl already has functionality so that a caller can abstract away all this complexity. It provides the capability in the _TclLoadFile_ call, but this call is **MODULE\_SCOPE** and not exported even in the internal Stubs table. For this reason, it is entirely unavailable to TEA-compliant extensions. If this call were available, it would be feasible, in the 8.6 time frame, to bundle all the database-specific TDBC drivers with the core TDBC distribution, since things could be set up so that they will build anywhere, even in the absence of the databases where they connect. However, this call was never fully rationalized in the VFS world. Its strange API \(with both a **Tcl\_LoadHandle** and a **ClientData**, and a function pointer for unloading the library\) is, as several reviewers pointed out, not somehting that we want to make available to general callers. Hence, a few more routines need rework. # Specification The _TclLoadFile_ call shall be renamed _Tcl\_LoadFile_ and exported in the external Stubs. Its call signature shall be changed to: > EXTERN int **Tcl\_LoadFile**\( Tcl\_Interp \*_interp_, Tcl\_Obj \*_pathPtr_, const char \*_symbols_[], int _flags_, void \*_procPtrs_, Tcl\_LoadHandle \*_handlePtr_\); In this call, _interp_ designates an interpreter for error reporting. _pathPtr_ is an object containing the path of the library to be loaded. If _pathPtr_ is a single name, the library search path of the current environment will be used to resolve it. The _symbols_ array contains a NULL-terminated set of character strings that are the names of the imported symbols. _symbols_ may be NULL if the library is to be loaded without resolving any symbols. The return value of _Tcl\_LoadFile_ is a standard Tcl result code. If the result is TCL\_ERROR, the interpreter result will contain an appropriate error message. On return, _Tcl\_LoadFile_ fills in the block of memory commencing at the address given by _procPtrs_ with the addresses that correspond to the names in _symbols._ If a name cannot be resolved in the given library, an error will be returned and all entries in _procPtrs_ will be invalid. _procPtrs_ may be NULL if no symbols are to be resolved. On a successful return, the _loadHandle_ pointer will be a handle suitable for passing to _Tcl\_FindSymbol_ for resolving additional symbols in the library, or to _Tcl\_FSUnloadFile_ to unload the library. The _TclpFindSymbol_ call shall be renamed _Tcl\_FindSymbol_ and exported in the external Stubs. Its call signature shall be: > EXTERN void\* **Tcl\_FindSymbol**\( Tcl\_Interp \*_interp_, Tcl\_LoadHandle \*_loadHandle_, const char \*_symbol_\); This call searches for the given _symbol_ in the already-loaded library identified by _loadHandle_. If the symbol is found, a pointer to its memory address is returned. Otherwise, NULL is returned, and an error message is left in _interp_ \(if _interp_ is not NULL\). A new call, _Tcl\_FSUnloadFile_ shall be introduced and exported in the external Stubs.Its call signature shall be: > EXTERN int **Tcl\_FSUnloadFile**\( Tcl\_Interp \*_interp_, Tcl\_LoadHandle \*_loadHandle_\); This call unloads the library identified by _loadHandle_. It differs from the [unload] command in that no 'unload' procedure is called; the library is simply unloaded without first being given a chance to clean itself up. \(This function is a lower-level interface used by [unload] as part of doing its work.\) The return value is either TCL\_OK or TCL\_ERROR; when TCL\_ERROR is returned, an appropriate message is left in the result of _interp_ \(if _interp_ is not NULL\). # Internals The **Tcl\_LoadHandle** object shall be represented internally by a structure, declared in <tclInt.h>, looking like: struct Tcl_LoadHandle_ { ClientData 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 */ } The _Tcl\_FindSymbolProc_ and _Tcl\_FSUnloadFileProc_ data types are declared to be functions of the same type signature as _Tcl\_FindSymbol_ and _Tcl\_FSUnloadFile_. Virtual file systems that implement the _loadFileProc_ are responsible for ensuring that their **Tcl\_LoadHandle_ that the _loadFileProc_ returns conforms with this convention. As far as the author has been able to determine, no non-Core filesystem provides anything but NULL for the _loadFileProc_. Certainly, tclvfs and trofs do not. Most other virtual filesystems layer atop tclvfs. # Reference Implementation A reference implementation is nearing completion, and the draft code is available attached to [Patch 2891616]<https://sourceforge.net/support/tracker.php?aid=2891616> at SourceForge. # License This file is explicitly released to the public domain and the author explicitly disclaims all rights under copyright law. |
Name change from tip/358.tip to tip/358.md.
|
| < | < | | | | | | | | > | | | | | | | | | | | | | | | | > | 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 | # TIP 358: Suppress Empty List Element Generation from the Split Command Author: George Petasis <[email protected]> State: Draft Type: Project Tcl-Version: 8.7 Vote: Pending Created: 04-Oct-2009 Post-History: Keywords: Tcl, list extraction, parsing ----- # Abstract The **split** command will create empty list elements when adjacent split characters are found in the input. In some cases these empty list elements are not desired, so this TIP proposes a new switch to disable their generation. # Rationale The idea for this TIP came from a discussion in comp.lang.tcl: <http://groups.google.gr/group/comp.lang.tcl/browse_thread/thread/8d46b0f10e7a5750/d7844cc739aa4310> and the \(non obvious\) suggestions on how tokens can be extracted from a string can be performed efficiently. It should be noted that this will allow the **split** command to be used in a fashion that is very similar to how splitting works in many other languages \(e.g., Perl, awk, Unix shells\). # Specification This TIP proposes a new optional switch \(**-noemptyelements**\) to the **split** command: > **split -noemptyelements** _string_ ?_splitChars_? If this option is present, then **split** will not produce an empty list element when the _string_ contains adjacent characters that are present in _splitChars_. # Reference Implementation Currently there is no patch, but it should be quite easy to implement this. # Copyright This document has been placed in the public domain. |
Name change from tip/359.tip to tip/359.md.
|
| < | < | | | | | | | | > | | | | | | | | | | | | | | | > | 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 | # TIP 359: Extended Window Manager Hint Support Author: Pat Thoyts <[email protected]> State: Final Type: Project Vote: Done Created: 21-Dec-2009 Post-History: Keywords: Tk,X11,ewmh,window manager Tcl-Version: 8.6 ----- # Abstract The **wm attributes** command will be extended to accept a **-type** option when running on the X Window system to manipulate the extended window manager hints for Tk toplevel windows. # Rationale This enhancement will enable script-level support for setting the extended window manager hints for Tk toplevel windows as specified in <http://standards.freedesktop.org/wm-spec/wm-spec-latest.html> . The **\_NET\_WM\_WINDOW\_TYPE** hint is used to provide information to the window manager about the intended use of a window so that appropriate decoration and animation can be applied. Specific examples of this include the dropdown listbox used with **ttk::combobox**, **tooltips**, splash screens and application dialog windows. Menus also need the type hint set appropriately but this has already been handled in the C code in recent commits. # Specification The **wm attributes** command for the X11 windowing system will have a new X11 platform-specific **-type** option which will return the current list of **\_NET\_WM\_WINDOW\_TYPE** atoms set for this **toplevel** or allow the list to be modified. The set of possible window type names is unconstrained to permit compatibility with future versions of the specification. However the window type names at the script level will be all lower-case and exclude any **\_NET\_WM\_WINDOW\_TYPE\_** prefix. As specified in the freedesktop.org document, the property is a list of hints with the types specified in order of preference as window managers may not implement some types. When setting a hint, the provided name is converted to upper-case, appended to **\_NET\_WM\_WINDOW\_TYPE\_** and converted to an atom. This permits new hints that may be specified in the future to be handled without modification to Tk. The Tk library scripts will set the type for all dialogs created by library functions and will set the combo hint for the **ttk::combobox** dropdown listbox. This feature is actually needed on 8.5 as well. Under compiz Tk window are inappropriately animated. The **combobox** dropdown in particular tends to bounce on Ubuntu. # Reference Implementation A patch is available at <https://sourceforge.net/support/tracker.php?aid=2918731> . # Copyright This document has been placed in the public domain. |
Name change from tip/36.tip to tip/36.md.
|
| < | < | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | < | > | | | > | 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 | # TIP 36: Library Access to 'Subst' Functionality Author: Donal K. Fellows <[email protected]> State: Final Type: Project Tcl-Version: 8.4 Vote: Done Created: 13-Jun-2001 Post-History: ----- # Abstract Some applications make very heavy use of the _subst_ command - it seems particularly popular in the active-content-generation field - and for them it is important to optimise this as much as possible. This TIP adds a direct interface to these capabilities to the Tcl library, allowing programmers to avoid the modest overheads of even _Tcl\_EvalObjv_ and the option parser for the _subst_ command implementation. # Functionality Changes There will be one script-visible functionality change from the current implementation; if the evaluation of any command substitution returns TCL\_BREAK, then the result of the _subst_ command will be the string up to that point and no further. This contrasts with the current behaviour where TCL\_BREAK \(like TCL\_CONTINUE\) just causes the current command substitution to finish early. # Design Decisions The code should be created by effectively splitting _Tcl\_SubstObjCmd_ in the current _.../generic/tclCmdMZ.c_ into two pieces. One of these pieces will have the same interface as the present code and will contain the argument parser. The other piece will be the implementation of the _subst_ behaviour and will be separately exposed at the C level as well as being called by the front-end code. The code should take positive flags stating what kinds of substitutions should be performed, as this is closest to the current internal implementation of the _subst_ command. These flags will be named with the prefix TCL\_SUBST\_\*. For programming convenience, the flag TCL\_SUBST\_ALL will also be provided allowing the common case of wanting all substitutions to be performed with a minimum of fuss. The string to be substituted will be passed in as a _Tcl\_Obj \*_ too, as this is both easiest to do from the point-of-view of the front-end code and permits additional optimisation of the core at some future point if it proves necessary and/or desirable. By contrast, passing in a standard C string or a _Tcl\_DString \*_ does not permit any such optimisations in the future. The code should return a newly-allocated _Tcl\_Obj \*_ as this allows for the efficient implementation of the front-end involving no re-copying of the resulting string. It also allows error conditions to be represented by NULL \(with an error message in the interpreter result\) and does not force a Tcl\_DString reference to be passed in as an _out_ parameter; returning the result gives a much clearer call semantics. Another advantage of using _Tcl\_Obj_s to build the result is the fact that they have a more sophisticated memory allocation algorithm that copes more efficiently with very large strings; when large and small strings are being combined together \(as is easily the case in _subst_\) this can make a substantial difference. # Public Interface _Added to .../generic/tcl.h_ #define TCL_SUBST_COMMANDS 0x01 #define TCL_SUBST_VARIABLES 0x02 #define TCL_SUBST_BACKSLASHES 0x04 #define TCL_SUBST_ALL 0x07 _Added to .../generic/tcl.decls_ declare someNumber generic { Tcl_Obj * Tcl_SubstObj( Tcl_Interp *interp, Tcl_Obj *objPtr, int flags) } # Implementation The implementation is to be developed upon acceptance of this TIP, but will involve _Tcl\_AppendToObj_ and _Tcl\_AppendObjToObj_. # Copyright This document has been placed in the public domain. |
Name change from tip/360.tip to tip/360.md.
|
| < | | | | | | < | | | > | | | | | | | | | | | | | | | | > | 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 | # TIP 360: Modernize X11 Menus Author: Pat Thoyts <[email protected]> Type: Project State: Final Vote: Done Created: 24-Dec-2009 Tcl-Version: 8.6 Keywords: Tk, X11, menu Post-History: ----- # Abstract This TIP proposes to modernize the functionality of the Tk menus on X11 to bring Tk up to date with reference to other toolkits on this platform. # Rationale Motif is dead and buried but Tk menus are still aping the Motif feel for **menu** handling on X11. Specifically all cascade menu items must be actively clicked to open the submenu. Other current toolkits work more like the Windows menus where once one of the menubar items has been clicked to activate its dropdown then subsequent mouse motion is sufficient to open any cascade menu on the menubar or from any of its dropdown menus. Tk provides magic handling for any menubar item whose name ends in **.help**. Specifically such a menu gets pinned to the extreme right of the menubar. This is sufficiently unusual that users often miss the help menu completely if they are used to Windows or GNOME applications. This is a hangover from 1990 and needs to go. # Specification The menu bindings will be modified to provide a concept of an activated menubar. Once any of the menubar cascade entries has been activated then the current active item will follow the mouse motion and explicit clicks will not be required to activate cascade entries. A small delay will be included when posting a cascade entry except when posting from the menubar. The activation is cancelled on hitting escape, selecting a menu entry or clicking outside the menu. If the new 'focus-follows-mouse' style behaviour is undesirable it can be disabled using the Tk options database. The Menu option **clickToFocus** may be set true to restore the original menu behaviour. This can be set using the Tk **option** command, the X resource database, or by calling **tk::classic::restore menu**. The special handling of **.help** menu entries in the menubar will be removed unless restored using the resource option **\*Menu.useMotifHelp**. This can be set using the Tk **option** command, the X resource database or by calling the **tk::classic::restore** command which will set the option along with some others. # Reference Implementation Patches posted as Tk patch item \#2920409 <https://sourceforge.net/support/tracker.php?aid=2920409> . # Copyright This document has been placed in the public domain. |
Name change from tip/361.tip to tip/361.md.
|
| < | < | | | | | | | > | | | | | | | | | | | > | 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 | # TIP 361: Releasing Channel Buffers Author: Wayne Cuddy <[email protected]> State: Draft Type: Project Vote: Pending Created: 03-Feb-2010 Tcl-Version: 8.7 Post-History: ----- # Abstract Tcl should provide a mechanism by which a channel's output buffer can be released without requiring that Tcl flush any remaining data in the buffer to the operating system. This is of particular interest with output mechanisms which can block indefinitely causing the interpreter to consume unnecessary resources or prevent the interpreter from exiting. # Problem When working with processes that handle multiplexing/non-blocking I/O it is not uncommon to write, or call **puts**, with more data than the operating system will accept. Thus Tcl begins to buffer this data using internal buffers at the application level and flushes the data in the background. Problems arise when the consumer of this data, be it the other end of a socket, pipe or FIFO, refuse to read data and do not close the channel. This has adverse effects on the **close** function and consequently the interpreter/process when it attempts to flush and close channels during finalization. ## Consequences 1. When **close** is issued on a non-blocking channel Tcl removes the channel from pool of accessible channels from the current interpreter and attempts to flush any remaining data in the output buffers before closing the channel. Since the other end of the channel is not consuming data Tcl will never be able to flush it's internal buffers nor close the lower level channel driver. In a multiplexing server which opens new channels this will eventually result in resource starvation or denial of service. 2. When **exit** is called Tcl attempts to flush all output buffers, if any open channel blocks the interpreter will be unable exit and must be forcibly terminated by OS specific mechanisms. # Propose API Additions Provide a function and/or flags to existing functions which can be used to clear internal buffers without flushing. * **chan clear** _channelId_ * **close -noflush** _channelId_ # Copyright This document has been placed in the public domain. |
Name change from tip/362.tip to tip/362.md.
|
| < | < | | | | | | | | | > | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 362: Simple 32 and 64 bit Registry Support Author: Damon Courtney <[email protected]> Author: Kevin Kenny <[email protected]> State: Final Type: Project Vote: Done Created: 01-Mar-2010 Post-History: Keywords: Windows,Tcl Tcl-Version: 8.6 ----- # Abstract Add new options to the **registry** command on Windows to allow it to specify that the action should be taken specifically on the 32 or 64 bit registry. # Rationale When Microsoft created a 64 bit version of Windows they had this idea of separating certain areas of the registry into a new node for 32 bit programs to access. The idea was that 64 bit programs would use the standard keys while 32 bit programs living in the 64 bit world would have their registry access shuffled off to a separate node behind their backs. By default, a 32 bit program will get the 32 bit registry node and a 64 bit program will get the 64 bit nodes, and in Tcl, this is what we're currently left to. It is possible to specify which registry you want to use through flags to the various registry commands, Tcl's **registry** command just doesn't know anything about them currently. # Specification The **registry** command will receive two new \(mutually exclusive\) options to specify that the given **registry** command should be executed against the 32 bit or 64 bit registry. The proposed implementation is the addition of a **-32bit** and a **-64bit** option, one of which may be placed before the _subcommand_ like so: > **package require registry 1.3** > **registry** ?**-32bit**\|**-64bit**? _subcommand_ ?_options_? By default, no option will mean that the **registry** command does what it has always done, which is to operate on the registry that matches the current compiled version of the running Tcl. Specifying **-32bit** means to operate on the 32 bit registry regardless of the current binary, and **-64bit** means to operate on the 64 bit registry. The options will be supported by all subcommands of **registry**. Concurrently with this change, the version number of the **registry** package will be advanced to 1.3. # Reference Implementation See Patch \#2960976 at SourceForge <https://sourceforge.net/support/tracker.php?aid=2960976> . # Copyright This document has been placed in the public domain. |
Name change from tip/363.tip to tip/363.md.
|
| < | < | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 363: Vector Math in the Tcl Core Author: Karl C. Hansen <[email protected]> State: Draft Type: Project Tcl-Version: 9.0 Vote: Pending Created: 02-Mar-2010 Post-History: Keywords: expand,{*},vector,math ----- # Abstract The "expand" operator - **\{\*\}** - was adopted in Tcl 8.5 and is very useful for simplifying code involving lists. It is proposed to add this operator to the list of actions performed during processing of double-quote \("\), joining the **$**, **[**, and **\\**, and to modify the behavior of **$** in variable substitution. The proposed behavior _will_ break existing substitution, but a trivial quoted-string substitution restores original behavior with the new approach. The proposed approach will enable eventual incorporation of vector-math to the Tcl engine without changing any of the existing syntax. # Rationale It is desired to enhance the current math engine in TCL to handle vector math, without having to create new syntax or add cumbersome new function calls. Given the assignments **set ScalarA 1**, **set ScalarB 2**, **set ListA \{1 2 3\}**, and **set ListB \{4 5 6\}**, evaluating **$ScalarA \+ $ScalarB**, **$ListA \+ $ListB**, and **$ListA \+ $ScalarB** would all be trivially understandable, with the first behaving as currently implemented, the second returning a list containing the element-by-element sums of the two lists, and the third returning a list containing the elements of ListA incremented by the common ScalarB. With the proposed enhancement \(see below\) the expression parser would receive a brace-delimited set of values wherever the lists appear, and a single value wherever the scalars appear. With the proposed enhancement, and a vector-math core enhancement, given the assignments above, the following would behave identically: expr $ListA + {4 5 6} expr $ListA + $ListB expr {1 2 3} + $ListB expr {1 2 3} + {4 5 6} With the proposed enhancement, incorporating vector math into the TCL core is vastly simplified, reducing to enhancing the current math handlers to perform different actions based on whether they received lists or scalars or both, and checking that the vectors have the appropriate element counts for the operation specified. # Proposal 1. Add expansion -- **\{\*\}** -- to set of actions performed during double-quote processing. > 1. Treat expand operator as a single character 'tri-graph'. > 2. Escape the operator -- **\\\{\*\}** -- to turn it into "regular text" causing it to behave as it currently does during double-quote processing. Note that this is identical with the current behavior of escape, i.e., **\\\{** currently gives **\{**. With the new implementation it turns the expand operator into normal text inside of a quoted string. 2. Modify **$** substitution so that _lists_ are enclosed in braces during substitution, i.e. after **set A \{1 2\}** execution of **puts "$A"** yields **\{1 2\}** instead of **1 2** as it currently does. Note that this behavior only manifests inside of quoted strings, as the assignment **set B $A** still gives the same results as the original implementation, i.e. assigning a list to **B**. > 1. Prefix **$** with expand **\{\*\}** to restore current behavior, i.e., with the same assignment above, execution of **puts "\{\*\}$A"** yields **1 2** instead of **\{\*\}1 2** as it currently does. Note that this provides a fairly simple way to fix scripts broken by implementing this proposal. If exising scripts contain quoted lists, simply \(a\) replace all double-quoted occurrances of **\{\*\}** with **\\\{\*\}**, and \(b\) replace all double-quoted occurrances of **$** with **\{\*\}$**. # Copyright This document has been placed in the public domain. |
Name change from tip/364.tip to tip/364.md.
|
| < | | | | | | | < | | > | | | | | | | | | | > | 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 | # TIP 364: Threading Support: Configuration and Package Author: Donal K. Fellows <[email protected]> State: Final Type: Project Tcl-Version: 8.6 Vote: Done Post-History: Created: 19-Mar-2010 Keywords: Tcl ----- # Abstract This TIP changes the the default configuration for building to threaded on all platforms where this is not already the case \(primarily Unix other than MacOS X\) and adds the Thread package to the set of packages included by default. # Rationale As the world of hardware changes, it is becoming clear that modern computers will increasingly have multiple CPU cores available to them. This is driven by the fact that it is easier for the manufacturers of processors to make them able to do more by increasing the number of cores than by increasing the speed of those cores. It is therefore a strongly-desirable thing to have Tcl able to utilize these resources and, naturally, in a cross-platform way. Threading is actually an area of considerable strength for Tcl. In particular, we have supported a threaded build of Tcl on all platforms since Tcl 8.1, and the performance cost of this is now minimal. In addition, the Thread package has been in use in production for a long time and provides script-level access to threading facilities. All that we need to do to fully enable Tcl 8.6 for threading for all scripts is to make the Thread package into a standard contributed package and ensure that it can be used on all our main supported platforms. It is this which this TIP proposes. # Proposed Change All that is required is to make the Thread package into one of the packages that is handled through the contributed package mechanism \(c.f., [incr Tcl] [[50]](50.md), TDBC [[308]](308.md)\), by locating a copy of it in the _pkgs/_ directory of the Tcl sources. However, to make this meaningful it is also necessary to alter the default configuration of Tcl to be threaded. This will have no effect on Windows and OSX, where threaded configurations are default anyway, but will have an impact on other Unixes \(Linux, Solaris, etc.\) The threaded configuration has had extensive testing over many years on all platforms, so it is known that a majority of Tcl scripts will be wholly unaffected by this. The main issues arising from this relate to the Expect and TclX packages. This is because they make **fork** and **signal** commands available; these APIs are troublesome because of how they interact with Tcl's notifier and the POSIX Thread system in general. However, the importance of threading as a general facility means that it is going to be more important to alter those packages than to keep Tcl defaulting to unthreaded. # Copyright This document has been placed in the public domain. |
Name change from tip/365.tip to tip/365.md.
|
| < | | | | | | < | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | < > | | | | | | | | < < | > > | > | 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 | # TIP 365: Add Python Compatibility Mode State: Draft Type: Project Tcl-Version: 8.6 Vote: No voting Post-History: Author: Donal K. Fellows <[email protected]> Created: 01-Apr-2010 Keywords: Look at the date ----- # Abstract This TIP adds support for reading and evaluating code written in Python to the _tclsh_ interpreter. # Rationale There is a lot of Python code out there, all of which suffers from the problem that the implementation quality of those interpreters is distinctly below what any reasonable person would consider "production". This presents a major opportunity for the well-known dynamic Tcl community to provide people across the whole world the power of Tcl \(especially through the new **case** command\) while requiring no changes on the users part other than a simple recoding of the calling sequence for their code. # Proposed Change A **PythonLanguageCompatibility** package will be provided. Upon being **package require**d, the remainder of the script will be evaluated in the Python language. This enables simple programs like this to be written: package require Tcl 8.6 interp create worker $worker eval { package require PythonLanguageCompatibility romanDgts= 'ivxlcdmVXLCDM_' def ToRoman(num): namoR = '' if num >=4000000: print 'Too Big -' return '-----' for rdix in range(0, len(romanDgts), 2): if num==0: break num,r = divmod(num,10) v,r = divmod(r, 5) if r==4: namoR += romanDgts[rdix+1+v] + romanDgts[rdix] else: namoR += r*romanDgts[rdix] + (romanDgts[rdix+1] if(v==1) else '') return namoR[-1::-1] } interp alias {} ToRoman $worker ToRoman after 100 {package require PythonLanguageCompatibility} after 200 {package forget PythonLanguageCompatibility} for {set i 0} {$i < 10000} {incr i} { try { print '%x - %s'%(i,ToRoman(i)) } trap {LANGUAGE WRONG} {} { puts "$i was not printed as a roman number" } } Clearly this allows the intermixing of both Tcl's and Python's strengths with minimal effort on users' parts. # Copyright This document has been placed in the public domain. |
Name change from tip/366.tip to tip/366.md.
|
| < | < | | | | | | | | > | | | | | | | | | | | | | > | 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 | # TIP 366: Variable Sized Indicators for Menubuttons Author: Russell Davidson <[email protected]> State: Draft Type: Project Vote: Pending Created: 29-Apr-2010 Post-History: Keywords: Tk Tcl-Version: 8.7 ----- # Abstract This TIP is to allow custom sizing of menubutton indicators using **-indwidth** and **-indheight** as options. # Rationale Currently there is no way to vary the size of the indicator for a classic Unix menubutton widget. Adding the ability to control this via configuration options will give the coder more control over a GUI's appearance for when such fine control is required. # Specification The following options are proposed to be added to the **::menubutton** widget: > The **-indwidth** option allows the specification of the width of the indicator in 10ths of a mm \(will be converted to an integer number of pixels\). > The **-indheight** option allows the specification of the height of the indicator in 10ths of a mm \(will be converted to an integer number of pixels\). # Implementation A patch exists in SourceForge \(Feature Request 2996760 <https://sourceforge.net/support/tracker.php?aid=2996760> \). # Copyright This document has been placed in the public domain. |
Name change from tip/367.tip to tip/367.md.
|
| < | | | | | | < | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | < | > | | | > | 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 | # TIP 367: A Command to Remove Elements from a List State: Draft Type: Project Tcl-Version: 8.7 Vote: Pending Post-History: Author: Donal K. Fellows <[email protected]> Created: 18-May-2010 Keywords: Tcl, delete, item ----- # Abstract This TIP proposes a command, **lremove**, that takes a list value and a collection of indices, and returns a list that is the input list with the elements at those indices removed. # Rationale Tcl has many operations for working with lists, such as **list** for building them, **lappend** for adding to them, **linsert** for insertion, **lreplace** for replacement of ranges, and **lset** for replacement of individual elements, but it has none that is designed to remove elements of a list. While the functionality can be simulated in the simple case with **lreplace**, this is rather more difficult when multiple indices are present. It is particularly challenging when using a mixture of indices that are defined relative to the start and the end of the list. Since the tools for doing the mapping of indices to list positions are easily available at the C level, I propose to add a command to Tcl to do the removal operation that takes advantage of the capabilities to do this all correctly. # Proposed Change This TIP proposes adding a command, **lremove**, with the following syntax: > **lremove** _list_ ?_index_? ?_index..._? That is, the command takes one mandatory argument, _list_, and an arbitrary number of _index_ arguments \(including zero\). The _list_ argument must be a valid Tcl list, and each of the _index_ arguments must be a valid Tcl index \(see [[176]](176.md) for a description\) where **end** will refer to the last element of _list_. Assuming syntactic validity, the result will be a list that is the same as _list_ except for the removal of the elements at each given _index_. The result shall be as if all removals happen simultaneously and the order of the _index_ arguments shall be unimportant; if an element is indicated twice \(whether through syntactically identical indices or not\) then it will be as if it was only indicated once. # Examples % lremove {a b c d e} 1 a c d e % lremove {a b c d e} end-1 a b c e % lremove {a b c d e} 1 3 a c e % lremove {a b c d e} 3 1 a c e % lremove {a b c d e} 2 2 a b d e % lremove {a b c d e} 3 end-1 a b c e % lremove {a b c d e} 1 3 1 4 0 c # Implementation _Pending._ # Copyright This document has been placed in the public domain. |
Name change from tip/368.tip to tip/368.md.
|
| < | < | | | | | | | | | > | | | | | | | | | | | > | 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 | # TIP 368: Listbox Justification Option Author: Russell Davidson <[email protected]> State: Withdrawn Type: Project Tcl-Version: 8.7 Vote: Pending Created: 10-May-2010 Post-History: Keywords: Tk Obsoleted-By: 441 ----- # Abstract This TIP is to allow right and center justification of listboxes using **-justify** as an option. # Rationale Sometimes a listbox needs right or center justification for the right visual effect. For example lists of numbers, particularly money amounts, look better right justified. Currently, only left justification is possible. # Specification It is proposed that a **-justify** option be added to the **::listbox** widget, which may be **left**, **right**, or **center** to allow different justifications. The default setting will be **left**. # Implementation A patch exists in SourceForge \(FRQ 2996762 <https://sourceforge.net/support/tracker.php?aid=2996762"> \). # Copyright This document has been placed in the public domain. |
Name change from tip/369.tip to tip/369.md.
|
| < | < | | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 369: Widget cargo command Author: Russell Davidson <[email protected]> Author: Trevor Davel <[email protected]> State: Draft Type: Project Vote: Pending Created: 15-Jul-2010 Post-History: Keywords: Tk,user-defined data,dictionary Tcl-Version: 8.7 ----- # Abstract This TIP is to add a **cargo** subcommand to widgets for storing data in a data dictionary. This TIP is related to [[349]](349.md). # Specification It is proposed that a **cargo** subcommand be added to most widgets that will allow the user to store data related to the widget in a data dictionary. With the **cargo** command there are three parameters that can go with it: **set**, **unset**, and **get**. **Set** adds and alters entries in the cargo dictionary. > _pathName_ **cargo set** _name value_ ?_name value ..._? **Unset**, with the name of an entry, will delete the entry from the cargo dictionary and free the memory that entry used. **Unset**, without an entry name, will delete the entire dictionary and free all memory. > _pathName_ **cargo unset** ?_name ..._? **Get** with the name of an entry will return the associated value. **Get** without an entry will return all entry-value pairs. > _pathName_ **cargo get** ?_name_? # Usage The following is based on a widget called _.wgt_ that has already been created: .wgt cargo set help "This is a widget" use "Shows a widget" This puts two entries into the cargo dictionary, one called _help_, with the value "_This is a widget_", and one called _use_ with the value "_Shows a widget_". .wgt cargo set help "This is a wonderful widget" use2 "Shows a great widget" This alters the value of the entry _help_ to "_This is a wonderful widget_", and adds the entry _use2_ with the value "_Shows a great widget_" .wgt cargo unset use This erases the entry _use_ and frees the memory. puts [.wgt cargo get help] This prints "_This is a wonderful widget_", the value of the entry _help_. puts [.wgt cargo get use] This prints an empty string because the entry _use_ has been deleted. When an entry that doesn't exist is accessed with **get**, a blank string is returned. puts [.wgt cargo get use2] This prints "_Shows a great widget_", the value of the entry _use2_. puts [.wgt cargo get] This prints "_help \{This is a wonderful widget\} use2 \{Shows a great widget\}_". .wgt cargo unset This deletes all entries and frees the memory Note that when a widget is destroyed, the cargo dictionary associated with it is erased and the memory is freed. # Rationale It is possible to duplicate this functionality by creating additional procedures and variables. But doing this in Tcl has the downside of creating more overhead when running the script. It also makes more things for the coder to keep track of. By putting the dictionary in the base code, there is less overhead and less for the developer to keep track of. If no cargo dictionary at all is wanted there is no additional overhead beyond an unused pointer in each widget. Memory management is a big benefit. As widgets are created/destroyed, it is easy to inadvertently generate memory leaks where structures are created for new widgets, filled with data, and then inadvertently left around after the widget is destroyed. When the data is stored with the widget instance, garbage gets cleaned up much more reliably. The **cargo** subcommand can also be used to help implement tool-tip funcionality. We could suggest that tool tips be supported natively in Tk, but that request would be easily argued against with the logic that it can be easily re-created in Tcl. So **cargo** is suggested instead as a very general way of facilitating a whole host of functionality to be implemented in widget wrappers without having to keep and maintain scads of external data in auxiliary hashes. One of the biggest challenges we face with Tcl/Tk is keeping it somewhat object oriented \(without having to inherit the whole overhead structure of one of the multitude of available OOPs\). When a new instance of a widget or a megawidget gets created, it is important to be able to keep track of which variables are related to instances and which ones apply to a whole class. We currently solve this by including the instance name in the hash index. While this works, it does get messy sometimes. And it would be appealing to be able to make individual instances of widgets responsible for storing their own data. It would certainly allow for a greater degree of isolation between instances. In short, **cargo** does not actually implement any specific functionality in the widget which a megawidget might otherwise handle. But it does facilitate easier implementation of a broad range of compound and megawidget functionality. # Implementation A patch exists in SourceForge \(FRQ 3023578 <https://sourceforge.net/support/tracker.php?aid=3023578> \) ---- # Comments Twylite 2010/08/10: * The performance overhead for doing this in a script rather than in the core is minimal. * Developer overhead is easily dealt with by means of an appropriate abstraction. * Script-level resource management can be achieved by binding to <Destroy>. * This proposal fails to address some variables that may need to be associated with a widget, in particular those used with -variable or -textvariable which require the ability to reference the variable by name. These are also instance-related variables that can benefit from automated resource management and a cleaner abstraction. * For a pure-Tcl implementation of functionality equivalent to **cargo** plus direct reference by name, take a look at my tk::wprop module \(doc <http://dev.crypt.co.za/incubator/doc/tcltm/tk/wprop.wiki> , source <http://dev.crypt.co.za/incubator/artifact/d480935465> \) ---- # Copyright This document has been placed in the public domain. |
Name change from tip/37.tip to tip/37.md.
|
| < | < | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 37: Uniform Rows and Columns in Grid Author: Peter Spjuth <[email protected]> Author: Kevin Kenny <[email protected]> State: Final Type: Project Vote: Done Created: 19-Jun-2001 Post-History: Tcl-Version: 8.4 ----- # Abstract This TIP proposes to add a _-uniform_ option to _grid rowconfigure_ and _grid columnconfigure_ so as to make it easier to create layouts where cells are constrained to have identical dimensions. # Introduction The geometry managers in Tk are very powerful and can do most things needed to layout a GUI. One thing that is tricky to do though is to put widgets in rows or columns of the same width. This would be useful for example to layout a row of buttons symmetrically. This could easily be done with the grid manager if an additional option is added. # Specification Anywhere _column_ is used below, the same applies to _row_ too. A new option, _-uniform_, is added to _grid columnconfigure_. The option takes an arbitrary string, the default value being the empty string. Any column with a non-empty value will be grouped with other columns with the same value. Each column in a group will get the size k\*_-weight_ \(in this aspect a _-weight_ value of 0 is used as 1\) , where k is set so that no column becomes smaller. E.g., if all columns in a group have the same _-weight_ they will all get the size of the largest member. In the grid algorithm _-uniform_ and _-weight_ will be used as specified above in the calculation of the requested size \(the first step in the description of the grid algorithm in grid\(n\)\), but for the distribution of extra size \(second step\) only _-weight_ will be considered. This means that the second step is not altered at all by this. # Rationale Getting symmetry in a layout today is possible but even for a simple case it gets tricky if you want more than a half decent result. Message catalogs changing strings and options databases changing appearances can make a GUI very dynamic and normally you never need to count pixels since geometry managers do that for you. For symmetry though you suddenly have to handle pixel details yourself, details that are handled so much better by a geometry manager. With a _-uniform_ option, grid can do symmetry for you in a simple way that takes care of all the details. To only consider _-weight_ in the extra size distribution is mainly a matter of simplicity. It gives a simpler algorithm that is both easier to explain to the user and to code. To uphold the uniform property it would be needed to force any zero _-weight_ value in a group where any non-zero _-weight_ exists to be set to one before doing the resize calculations. A bit complicated and the only benefit for the user would be to only have to specify _-weight_ for one column in a group. But in practice this is hardly no gain at all since a typical usage looks like this: grid columnconfigure . {0 1 2} -uniform a -weight 1 I'm not sure if someone would have a use for the effect you would get by mixing zero and non-zero weights in a group but this leaves you the freedom to do so. # Examples To clarify how -uniform affects a grid here are some examples. button .b1 -text a button .b2 -text b button .b3 -text example button .b4 -text xyzzy grid .b1 .b2 .b3 .b4 -sticky news grid columnconfigure . {0 1 2 3} -uniform a -weight 1 Initially all columns will be equal and if resized, all columns will change equally. Initial: |[ a ]|[ b ]|[example]|[ xyzzy ]| Shrunk: |[ a ]|[ b ]|[xampl]|[xyzzy]| Another example. Instead we do: grid columnconfigure . {0 2} -uniform a -weight 1 grid columnconfigure . {2} -weight 2 grid columnconfigure . {1 3} -uniform b -weight 0 grid columnconfigure . {1} -weight 1 Initially column 0 will be half the size of column 2, columns 1 and 3 will be equal. Resizing will affect colums 0 and 1 half of how column 2 is affected. Column 3 is static. Initial: |[ a ]|[ b ]|[example]|[xyzzy]| Shrunk: |[a]|[ b ]|[amp]|[xyzzy]| Expanded: |[ a ]|[ b ]|[ example ]|[xyzzy]| # Implementation A quick try shows that this is fairly straightforward to implement. If the option is not used the memory cost is a _Tk\_Uid_ field \(or similar if some other mechanism than _Tk\_Uid_ is used\) in the column slot structure to hold the option, and the CPU overhead is small. # Summary of Objections * Kevin Kenny raised the issue that the proposed implementation uses a Tk\_Uid for the "uniform" key, leading to potential resource leaks. Subsequent discussion has convinced him that the potential for trouble is small; in any case, it need not block approval. The ensuing discussion veered off into a long thread about reclaiming the memory used for Tcl\_Obj structures; the thread is not pertinent to this TIP. * George Howlett questioned the need for this feature, citing the lack of compelling examples. The original author replied with the example of a dialog holding multiple buttons containing text of different widths, and showed how the Tcl code to manage such a dialog is clumsy. * George Howlett raised the issue of a detailed specification of the behavior of -uniform when insufficient space is available to satisfy the request. The original author added clarification in the "Examples" section, and supplied additional examples in discussions on the mailing list <http://www.geocrawler.com/archives/3/7375/2001/7/50/6211900/> . * George Howlett also asserted that the desired semantics can be achieved with Tcl code that either lays out a fixed configuration of the widget \(with, for example, the _-minsize_ option of _grid columnconfigure_\) or responds to the _<Configure>_ event. Probably the best summary of the ensuing discussion is that we need to strike a balance between richness of the API and simplicity of the implementation. # Copyright This document has been placed in the public domain. |
Name change from tip/370.tip to tip/370.md.
|
| < | < | | | | | | | > | | | | | | | | | | | | | | | | > | 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 | # TIP 370: Extend Tk's selection with a -time option Author: George Petasis <[email protected]> State: Draft Type: Project Tcl-Version: 8.7 Vote: Pending Created: 04-Aug-2010 Post-History: ----- # Abstract This TIP proposes the addition of a new argument to the Tk command **selection**, for specifying a timestamp that should be used in order to retrieve a selection. # Rationale TkDND 2.x always used the **selection** command to retrieve data from the clipboard, and worked until recently. The problem seems to be that the selection Tk command always uses "_CurrentTime_" while retrieving the selection, while the XDND protocol specifies that a specific timestamp should be used. I see that in Tk sources \(_unix/tkUnixSelect.c_, line 178, the call to _XConvertSelection_\) there is already some discussion in the comments which timestamp should be used. The "_CurrentTime_" seems a good choice, but why not offer the ability to provide a timestamp if needed? # Proposed Change Add a new option to **selection get**. Something like this: > **selection get** ?**-displayof** _window_? ?**-selection** _selection_? ?**-type** _type_? ?**-time** _time_? The _time_ value will be an integer, the same as in the **-time** option to **event generate** and as produced by the **%t** substitution in **bind**. # Copyright This document has been placed in the public domain. |
Name change from tip/371.tip to tip/371.md.
|
| < | < | | | | | | | | > | | | | | | | < | > | | | | | | | | | | | | | | > | 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 | # TIP 371: Improvements for the dict command Author: Thomas Perschak <[email protected]> Author: Trevor Davel <[email protected]> State: Draft Type: Project Vote: Pending Created: 05-Aug-2010 Post-History: Tcl-Version: 8.7 ----- # Abstract The **dict** command is limited by allowing manipulation of only the first level of key elements. Not only should the **dict get** accept a nested key list, but also the other commands like **dict replace**. # Specification And Example The following line: dict get {-range {-values {a b c} -base M} -name myname} \ -range -base Results in: M But how to change the base? I suggest the following **dict** syntax extension: dict replace {-range {-values {a b c} -base M} -name myname} \ {-range -base} k Results in: -range {-values {a b c} -base k} -name myname Allowing a nested key list would not break any previous code, but substantially improve the **dict** command. # Rationale The **dict** command is the basis for handling database like structures. By allowing nested keys this would give more freedom in organizing these structures like the example above. ---- # Comments Twylite 2010/08/17: The specification states that "Allowing a nested key list would not break any previous code". This is not correct, for example: dict replace {"Jane Smith" "11 Foo Road" "John Doe" "Address unknown"} {Jane Smith} new_address -> {Jane Smith} new_address {John Doe} {Address unknown} Existing code that uses **dict replace** in conjunction with keys that are valid lists of 2 or more elements would break. Also, drawing from experience, the nested key approach is a source of subtle bugs. It is natural to write code such as: dict replace $dict $key $value but that contains a bug that is often missed during testing. The correct approach would be: dict replace $dict [list $key] $value ---- # Copyright This document has been placed in the public domain. |
Name change from tip/372.tip to tip/372.md.
|
| < | < | | | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 372: Multi-argument Yield for Coroutines Author: Colin McCormack <[email protected]> State: Draft Type: Project Vote: Done Created: 11-Aug-2010 Post-History: Tcl-Version: 8.6 Discussions-To: http://wiki.tcl.tk/26006 Keywords: coroutine, yield Obsoleted-By: 396 ----- # Abstract This TIP proposes a command that allows a coroutine to accept multiple arguments being passed in on return from yield. # Rationale The coroutine mechanism of [[328]](328.md) has given Tcl 8.6 a new primitive which permits light-weight mulitasking. The mechanism as specified by [[328]](328.md) lacks the ability to emulate general-purpose procedural invocation through the arbitrary limitation of coroutine calls to a single argument \(except on the initial call\). The ability of coroutines to emulate general-purpose procedural invocation is of great utility, the lack of which leads to stilted verbiage, and diverges unnecessarily from Tcl's other functionals. The **yieldm** command, as currently implemented by **::tcl::unsupported::yieldm**, extends coroutines to permit general emulation, and it is the proposal of this TIP that yieldm be moved to the global namespace, or such other namespaces as may be used for coroutine functionality in the future. # Syntax and Semantics of yieldm > **yieldm** ?_value_? This is just like **yield**, except that it causes the coroutine command to accept arbitrarily many arguments and will return the list of those arguments \(i.e., an empty list if there are no arguments, a single-element list if there is one, a pair for two, etc.\) # Detailed Rationale ## Utility Restatement-in-summary of the arguments in <http://wiki.tcl.tk/26006:> 1. Coroutines should be able to simulate any command, not just any single-arg'd command. [Argument: generality] 2. To implement single-arg's coroutines in multi-arg'd coroutines is trivial - nothing needs to be done. The converse \(implementing multi-arg'd coroutines under coroutine is inefficient and difficult. [Argument: increased expressive power] 3. There is no sound reason that the invocation of a coroutine should not resemble that of any other command. [Argument: principle of minimal surprise] 4. It is impossible to construct forms like **interp alias** to address a coroutine in the common case that the caller is expecting to pass more than one argument. ## Consistency Restatement-in-summary of the arguments in <http://wiki.tcl.tk/26056:> The following commands create new commands: **proc**, **coroutine**, **namespace ensemble**, **class create**, _$cls_ **create**, **interp alias**, **interp create**, **::thread::create**, **apply**. In each case except **coroutine**, the created command permits multiple arguments \(arguably this being a key feature of Tcl in practice\). There is no sound reason for this disparity, and for consistency the disparity should be removed, which the proposed **yieldm** does. # Implementation Simply rename the **::tcl::unsupported::yieldm** into the global namespace, and extend the coroutine documentation to refer to the new command. # Copyright This document has been placed in the public domain. |
Name change from tip/373.tip to tip/373.md.
|
| < | < | | | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 373: Improved Yielding Support for Coroutines Author: Miguel Sofer <[email protected]> State: Withdrawn Type: Project Vote: Pending Created: 12-Aug-2010 Post-History: Keywords: coroutine,yield Obsoletes: 372 Obsoleted-By: 375 Tcl-Version: 8.6 ----- # Abstract This TIP proposes two new commands that improve control over the yielding behaviour of coroutines. # Rationale The new command **yieldto** allows a coroutine to suspend its execution and tailcall into an arbitrary command. It provides support for symmetric coroutines, simply specifying that the new command be another coroutine's resume command. The new command **yieldset** specifies the number of arguments that the coroutine's resume command will accept. Note that **yieldset** obsoletes [[372]](372.md), in the sense that it provides a different way of satisfying the same needs. ## Detailed Rationale for "yieldto" The current **yield** and proposed **yieldm** suspend a coroutine and return the control to the coroutine's caller: they implement asymmetric coroutines. It is well known that symmetric and asymmetric coroutines have equal power, in that each can be implemented on top of the other. In Tcl8.6 as of today, symmetric coroutines can be implemented by coding a scheduler, which may but doesn't have to use the event loop. The new command **yieldto** implements symmetric coroutines directly. The ability of **yieldto** to yield to an arbitrary command also provides new possibilities. For instance, it allows to return a non-ok code to the caller without terminating the coroutine: yieldto return -level 0 -code 1 ERROR # Proposal for "yieldto" The new command > **yieldto** _cmd_ ?_arg1 ..._? causes: 1. the currently executing coroutine to suspend its execution \(yield\), 2. the command built from the arguments to **yieldto**, as resolved in the coroutine's context, is run in the coroutine's caller scope, 3. from the point of view of the coroutine's caller, the return value and options of the new command is what the coroutine returned on yielding. In other words, **yieldto** implements "suspend yourself and **tailcall** the new command"; **yieldto** is to **yield** as **tailcall** is to **return**. ## Implementation of "yieldto" Simply rename the **::tcl::unsupported::yieldTo** into the global namespace while getting rid of the camelCase, and extend the **coroutine** documentation and test-suite to refer to the new command. # Rationale and Proposal for "yieldset" [[372]](372.md) justifies and requests a different interface to a coroutine's resume command, allowing for an arbitrary number of arguments that shall be returned to the coroutine's body in a list. In order to limit the number of additional commands \(**yieldm** and also **yieldmto**\), and increase the flexibility, it is proposed to add a command: > **yieldset** ?_arglist_? that sets the acceptable arguments for the resume command. If **yieldset** is called with no arguments it returns the current list of arguments. If **yieldset** is called with a list argument, it specifies the arguments to the resume command in the manner of **proc**. The argument names shall only be used for the error message if the resume command is called with an invalid number of arguments. In this manner, current **yield** behaves as if yieldset {{arg {}}} had been called. This shall remain the default behaviour. If **yieldset** is called outside of a coroutine context, it sets the default behaviour for newly created coroutines. If it is called within a coroutine context it sets the behaviour for the current coroutine only. In order to obtain [[372]](372.md)'s **yieldm** behaviour for **yield**, it would be necessary to call: yieldset args either before creating the coroutine or else within the coroutine body. The default arglist shall be **\{\{arg \{\}\}\}**, so that the current **yield** is the default behaviour. The arglist value can be changed with **yieldset** at any time, and remains valid until changed again. # Caveat Some new proposals for better coroutine interfaces are being discussed, based on ensembles and providing additional functionality. I do not foresee the discussion to settle in the immediate future. The current TIP is not meant to preempt any such design, it just attempts to provide a limited improvement that is easy to implement immediately. # Copyright This document has been placed in the public domain. |
Name change from tip/374.tip to tip/374.md.
|
| < | < | | | | | | | | > | | | | | | | | | | | | | | | | | | | | < | > | | | | | | | | | < | > | | | | | < | > | | | | | < | > | | | > | 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 | # TIP 374: Stackless Vwait Author: Thomas Perschak <[email protected]> Author: Trevor Davel <[email protected]> State: Draft Type: Project Vote: Pending Created: 13-Aug-2010 Post-History: Tcl-Version: 8.7 ----- # Abstract This TIP proposes a way to have multiple procedures waiting for an event to happen, where the command that gets executed depends on the order of the events. # Rationale Suppose you have three \(or even more\) synchronous procedures each of them waiting for the socket to be readable. This waiting is implemented with **vwait** - it is not possible to call this procedure event-driven - the socket is opened and closed inside the same procedure. The current implementation of **vwait** would block the procedure which called **vwait** first, till the last procedure has read all data. The stackless **vwait** would allow to group all similar **vwait** calls, define them stackless as whoever-comes-first and so unblock the procedure which has first data to read. Originally I thought this could be solved with coroutines but I'am not so sure any more. Anyhow I think that the problem - explained later below - could be solved with a stackless **vwait** in a very elegant way. Currently the **vwait** command is last-in-first-out, on the basis of the stackless 8.6 core there could be an improvement to make the **vwait** command configurable as last-in-last-out or even completely stackless event driven. # Specification This is only a first idea, but it could be similar to named-mutex definitions - so one as to define the group of the **vwait** waiting for and the three behaviour types: first-in-last-out, first-in-first-out, whoever-comes-first; The following command creates a new vwait group with a specified stack behaviour: vwaitgroup myvwaitgroup whoever-comes-first Finally comes the waiting for the **vwait** which is similar to the existing one: vwaitnew<myvar> myvwaitgroup In addition I would allow a timeout value to be specified: vwaitnew<myvar> myvwaitgroup<mytimeout> # Example This is only a very reduced example, but should show the principle of the problem: proc myproc1 {} { open socket fileevent socket {set myvar 1} vwait myvar read data } Having more than one of these procedure above, the **vwait** would block data reading depending on the **vwait** stack. The new stackless **vwait** would look like the following example: On a global level I would do the following: vwaitgroup sockreadgroup whoever-comes-first Then the procedures: proc myproc1 {} { open socket fileevent socket {set myvar 1} vwait myvar sockreadgroup read data } proc myproc2 {} { open socket fileevent socket {set myvar 1} vwait myvar sockreadgroup read data } proc myproc3 {} { open socket fileevent socket {set myvar 1} vwait myvar sockreadgroup read data } ---- # Comments Twylite 2010/08/17: "coroutine-enabled event handling" \(<http://wiki.tcl.tk/21555\)> presents pure-Tcl implementations of coroutine-enabled **vwait** and **gets** that do what this TIP describes without attempting to implement a custom scheduler. ---- # Copyright This document has been placed in the public domain. |
Name change from tip/375.tip to tip/375.md.
|
| < | < | | | | | | | | | | > | | | | | | | | | | | | | | | | | | > | 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 | # TIP 375: Symmetric Coroutines and Yieldto Author: Miguel Sofer <[email protected]> State: Draft Type: Project Vote: Done Created: 12-Aug-2010 Post-History: Keywords: coroutine,yield Obsoletes: 373 Obsoleted-By: 396 Tcl-Version: 8.6 ----- # Abstract The new command **yieldto** allows a coroutine to suspend its execution and tailcall into an arbitrary command. If the new command is another coroutine's resume command we obtain symmetric coroutines. ## Rationale The current **yield** and proposed **yieldm** commands suspend a coroutine and return the control to the coroutine's caller: they implement asymmetric coroutines. It is well known that symmetric and asymmetric coroutines have equal power, in that each can be implemented on top of the other. In Tcl8.6 as of today, symmetric coroutines can be implemented by coding a scheduler, which may but doesn't have to use the event loop. The new command **yieldto** implements symmetric coroutines directly. The ability of **yieldto** to yield to an arbitrary command also provides new possibilities. For instance, it allows to return a non-ok code to the caller without terminating the coroutine: yieldto return -level 0 -code 1 ERROR # Proposal for "yieldto" The new command > **yieldto** _cmd_ ?_arg1 ..._? causes: 1. the currently executing coroutine to suspend its execution \(yield\), 2. the command built from the arguments to **yieldto**, as resolved in the coroutine's context, to be run in the coroutine's caller scope, 3. from the point of view of the coroutine's caller, the return value and options of the new command is what the coroutine returned on yielding. In other words, **yieldto** implements "suspend yourself and **tailcall** the new command"; **yieldto** is to **yield** as **tailcall** is to **return**. ## Implementation of "yieldto" Simply rename the **::tcl::unsupported::yieldTo** into the global namespace while getting rid of the camelCase, and extend the **coroutine** documentation and test-suite to refer to the new command. # Copyright This document has been placed in the public domain. |
Name change from tip/376.tip to tip/376.md.
|
| < | < | | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 376: Bundle sqlite3 and tdbc::sqlite3 Packages Author: Don Porter <[email protected]> Author: D. Richard Hipp <[email protected]> Author: Kevin Kenny <[email protected]> State: Final Type: Project Vote: Done Created: 14-Sep-2010 Tcl-Version: 8.6 Post-History: ----- # Abstract This TIP proposes the packages **sqlite3** and **tdbc::sqlite3** be re-distributed as part of the Tcl source code distribution. # Background Starting with the 8.6.\* releases of Tcl, a collection of third party packages are being redistributed as part of the Tcl source code distribution under the directory _tcl/pkgs/_. This is partial fulfillment of the long-awaited _batteries included_ vision for Tcl releases. The current collection of redistributed packages is Itcl [[50]](50.md), Thread [[364]](364.md), and tdbc [[308]](308.md). The sqlite3 package is perhaps the most striking example of a Tcl extension that has grown to eclipse Tcl itself. Created and maintained by TCT emeritus D. Richard Hipp, it should require little explanation here. The tdbc::sqlite3 package provides the driver functionality to use the facilities provided by sqlite3 as the backend of tdbc operations. Created and maintained by Kevin Kenny of the TCT, it should also be familiar to Tcl insiders. # Proposal Adapt release operations as needed so that the latest releases of the **sqlite3** and **tdbc::sqlite3** packages are included in releases of Tcl 8.6.\*. # Expected Benefits Distribution of the **tdbc** package without any backend drivers has quite limited utility. Adding these two packages to the distributed set provides at least one fully working backend with no third-party dependencies. This permits testing and demonstrating the capabilities of **tdbc** everywhere it goes. By including **sqlite3** in the Tcl source code distribution, Tcl can take a place alongside PHP and Python on the list of famous users of SQLite <http://www.sqlite.org/famous.html> . Since SQLite is now easily more broadly esteemed than Tcl itself, this can only help our public image. The package **tdbc::sqlite3** is itself written entirely in Tcl. Unlike the packages so far chosen for redistribution under _tcl/pkgs/_, it contains no C code. The _tcl/pkgs/_ harness and the TEA or tclconfig systems it descends from have so far not paid sufficient attention to this case. Including this package will force those systems over time to better support that common implementation case. This can only make package support tools better for more package authors. Also, as support for such packages under _tcl/pkgs/_ matures, the large collection of packages that have been distributed with Tcl on a more ad hoc basis, including **tcltest**, **msgcat**, **http**, **platform**, and **platform::shell**, may be able to migrate to new places under the _tcl/pkgs/_ framework. This may eventually lead to the ability to selectively take packages from tcllib for redistribution with Tcl. # Copyright This document has been placed in the public domain. |
Name change from tip/377.tip to tip/377.md.
|
| < | < | | | | | | | > | | | | | | | | | | | | | | | | | > | 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 | # TIP 377: Portably Determining the Number of Processors in the System Author: Andreas Kupries <[email protected]> State: Withdrawn Type: Project Vote: Pending Created: 13-Sep-2010 Tcl-Version: 8.6 Post-History: ----- # Abstract A C API and Tcl command are proposed which return the number of CPUs \(a.k.a. Processors a.k.a. Cores\) in the system, portably wrapping the OS specific APIs for doing so. # Background and Motivation With the relentless advance of multi-core chips it becomes sensible, IMVHO, to have a portable method of determining the number of CPUs \(also called Processors or Cores\) in the system. This information is mostly important for the initialization of thread pools, in order to have a sensible number of worker threads which provide the maximum speedup without overloading the system. The general use-case the previous is an example of is the dynamic reconfiguration of an application or library to automatically adapt it to the resources available in the environment it finds itself in. That is, this is useful for multi-process applications as well. Semi-concrete examples: The CRIMP package is currently single-threaded. For the best parallelization by threading, it should be possible to query the number of processors the application can use. A web server like Wub can make use of this functionality as well. They should not have to implement this on their own, duplicating the functionality, or, worse, each having slightly different implementations. # C Level API > int **Tcl\_GetNumberOfProcessors**\(int _flags_\) Returns the number of processors for the current system, as provided by the OS. If the system is unable to provide this information the returned value is '1', as at least one processors is necessary to run anything at all. The _flags_ argument is not used. It is provided as a means of extensibility. Something which can be used in the future to distinguish between physical processors, hyperthreaded virtual processors, cores on a chip, number of processor chips, and the like. Right now such advanced queries are out of the scope of the TIP. The main point of having the 'flags' argument now is that future extensions using it will not have to change the signature of the function. # Script Level API > **info processors** Returns the number of processors for the current system, as provided by **Tcl\_GetNumberProcessors**\(0\). # Reference Implementation A reference implementation is provided at SourceForge <https://sourceforge.net/support/tracker.php?aid=3065485> . # Discussion The stackoverflow messaging board has a question on the various OS-specific APIs. See <http://stackoverflow.com/q/150355/301832> for details. # Copyright This document has been placed in the public domain. |
Name change from tip/378.tip to tip/378.md.
|
| < | < | | | | | | | | > | | | | | | | | | | | | | | | | | | > | 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 | # TIP 378: Fixing the Performance of TIP 280 Author: Andreas Kupries <[email protected]> Author: Jeff Hobbs <[email protected]> State: Final Type: Project Vote: Done Created: 04-Oct-2010 Tcl-Version: 8.6 Post-History: ----- # Abstract A Tcl command is proposed which enable a user of Tcl to disable the most performance intensive parts of the [[280]](280.md) implementation, at the loss of some detail. # Background and Motivation [[280]](280.md) extended Tcl's abilities for introspection with the **info frame** command able to determine the location of its call, i.e., the name of the file the code is in, and the absolute line number in that file. In the quest for the best possible detail one particular part of the implementation had a great impact on the performance of bytecode execution, doing complex stack/hash manipulations for each argument of each INST\_INVOKE\_STK instruction to keep track of the location of scripts delivered to **uplevel** commands as arguments of Tcl procedures \(i.e., implementations of control structures in Tcl\). This TIP now proposes to put the execution of this part of [[280]](280.md)'s implementation under user control, allowing them to trade **info frame**-exactness for speed, and vice versa. # Script Level API > **interp debug** _interp-path_ ?**-frame** ?_boolean_?? This API was chosen to be potentially extensible for other future interpreter level control needs. ## Default Setting This behavior will be turned off by default, unless Tcl is compiled with -DTCL\_INTERP\_DEBUG\_FRAME or $::env\(TCL\_INTERP\_DEBUG\_FRAME\) is set at interpreter creation time. Note that this is a one-way switch because the **info frame** tracking is maintained in a stack that must remain consistent once switched on. Switching off when deep in the stack would cause memory loss and possible crashes without tracing on top of tracing, and it is felt that being an interp-level switch, one-way switching should be sufficient for user needs. # Reference Implementation A reference implementation is provided at SourceForge <https://sourceforge.net/support/tracker.php?aid=3081184> . # Copyright This document has been placed in the public domain. |
Name change from tip/379.tip to tip/379.md.
|
| < | < | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 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 | # TIP 379: Add a Command for Delivering Events Without Tk Author: Will Duquette <[email protected]> State: Draft Type: Project Tcl-Version: 8.7 Vote: Pending Created: 17-Oct-2010 Post-History: Keywords: event ----- # Abstract This proposal defines the **hook** ensemble command, which implements the Subject/Observer pattern. It allows _subjects_, which may be modules, objects, widgets, and so forth, to synchronously call _hooks_ which may be bound to an arbitrary number of subscribers, called _observers_. A subject may call any number of distinct hooks, and any number of observers can bind callbacks to a particular hook called by a particular subject. Hook bindings can be queried and deleted. # Rationale Tcl modules usually send notifications to other modules in two ways: via Tk events, and via callback options like the text widget's **-yscrollcommand** option. Tk events are available only in Tk, and callback options require tight coupling between the modules sending and receiving the notification. Loose coupling between sender and receiver is often desirable, however. In Model/View/Controller terms, a View can send a command \(stemming from user input\) to the Controller, which updates the Model. The Model can then call a hook _to which all relevant Views subscribe._ The Model is decoupled from the Views, and indeed need not know whether any Views actually exist. At present, Tcl/Tk has no standard mechanism for implementing loose coupling of this kind. This proposal defines a new command, **hook**, which implements just such a mechanism. # Hook Bindings The **hook** command manages a collection of hook bindings. A hook binding has four elements: * A _subject_: the name of the entity that will be calling the hook. * The _hook_ itself. A hook usually reflects some occurrence in the life of the _subject_ that other entities might care to know about. A _hook_ has a name, and may also have arguments. Hook names are arbitrary strings. Each _subject_ must document the names and arguments of the hooks it can call. * The name of the _observer_ that wishes to receive the _hook_ from the _subject_. * A command prefix to which the _hook_ arguments will be appended when the binding is executed. ## Subjects and Observers For convenience, this TIP collectively refers to subjects and observers as _objects_, while placing no requirements on how these _objects_ are actually implemented. An object can be a a TclOO or Snit or XOTcl object, a Tcl command, a namespace, a module, a pseudo-object managed by some other object \(as tags are managed by the Tk text widget\) or simply a well-known name. Subject and observer names are arbitrary strings; however, as **hook** might be used at the package level, it's necessary to have conventions that avoid name collisions between packages written by different people. Therefore, any subject or observer name used in core or package level code should look like a Tcl command name, and should be defined in a namespace owned by the package. Consider, for example, an ensemble command **::foo** that creates a set of pseudo-objects and uses **hook** to send notifications. The pseudo-objects have names that are not commands and exist in their own namespace, rather like file handles do. To avoid name collisions with subjects defined by other packages, users of **hook**, these **::foo** handles should have names like **::foo::1**, **::foo::2**, and so on. Because object names are arbitrary strings, application code can use whatever additional conventions are dictated by the needs of the application. # Specification The **hook** command is an ensemble command with the following subcommands: ## Bind Subcommand This subcommand is used to create, update, delete, and query hook bindings. > **hook bind** ?_subject_? ?_hook_? ?_observer_? ?_cmdPrefix_? Called with no arguments, **hook bind** returns a list of the subjects with hooks to which observers are currently bound. Called with one argument, a _subject_, **hook bind** returns a list of the subject's hooks to which observers are currently bound. Called with two arguments, a _subject_ and a _hook_, **hook bind** returns a list of the observers which are currently bound to this _subject_ and _hook_. Called with three arguments, a _subject_, a _hook_, and an _observer_, **hook bind** returns the binding proper, the command prefix to be called when the hook is called, or the empty string if there is no such binding. Called with four arguments, **hook bind** creates, updates, or deletes a binding. If _cmdPrefix_ is the empty string, **hook bind** deletes any existing binding for the _subject_, _hook_, and _observer_; nothing is returned. Otherwise, _cmdPrefix_ must be a command prefix taking as many additional arguments as are documented for the _subject_ and _hook_. The binding is added or updated, and the observer is returned. If the _observer_ is the empty string, "", **hook** will create a new binding using an automatically generated observer name of the form **::hook::ob**<_number_>. The automatically generated name will be returned, and can be used to query, update, and delete the binding as usual. If automated observer names are always used, the observer name effectively becomes a unique binding ID. ### Binds During Calls It is possible to call **hook bind** to create or delete a binding to a _subject_ and _hook_ while in an observer binding for that same _subject_ and _hook_. The following rules determine what happens when **hook bind $s $h $o $binding** is called during the execution of **hook call $s $h**: * No binding is ever called after it is deleted. * When a binding is called, the most recently given command prefix is always used. * The set of observers whose bindings are to be called is determined when **hook call** begins to execute, and does not change thereafter, except that deleted bindings are not called. In particular: * If $o's binding to $s and $h is deleted, and $o's binding has not yet been called during this execution of **hook call $s $h**, it will not be called. \(Note that it might already have been called; and in all likelihood, it is probably deleting itself.\) * If $o changes the command prefix that's bound to $s and $h, and if $o's binding has not yet been called during this execution of **hook call $s $h**, the new binding will be called when the time comes. \(But again, it is probably $o's binding that is is making the change.\) * If a new observer is bound to $s and $h, its binding will not be called until the next invocation of **hook call $s $h**. ### Discussion **Optional Observers:** It has been suggested that the _observer_ argument should follow the _cmdprefix_ argument; if it is omitted, an observer name would be automatically generated. However, the _observer_ name is frequently used in practice, and is likely to be much shorter than the _cmdprefix_, which might be quite long. As a general rule, short arguments following long ones tend to get lost visually; keeping the _observer_ before the _cmdprefix_ leads to more easily readable code. ## Call Subcommand > **hook call** _subject hook_ ?_args..._? This command is called when the named _subject_ wishes to call the named _hook_. All relevant bindings are called with the specified arguments in the global namespace. Note that the bindings are called synchronously, before **hook call** returns; this allows the _args_ to include references to entities that will be cleaned up as soon as the hook has been called. The order in which the bindings are called is not guaranteed. If sequence among observers must be preserved, define one observer and have its bindings call the other callbacks directly in the proper sequence. Because the **hook** mechanism is intended to support loose coupling, it is presumed that the _subject_ has no knowledge of the observers, nor any expectation regarding return values. This has a number of implications: * **hook call** returns the empty string. * Normal return values from observer bindings are ignored. * Errors and other exceptional returns propagate normally by default. This will rarely be what is wanted, because the subjects usually have no knowledge of the observers and will therefore have no particular competence at handling their errors. That makes it an application issue, and so applications will usually want to define an **-errorcommand**. If the **-errorcommand** configuration option has a non-empty value, its value will be invoked for all errors and other exceptional returns in observer bindings. See **hook configure**, below, for more information on configuration options. Also, see below for possible extensions to **hook call**. ## Forget Subcommand > **hook forget** _object_ This command deletes any existing bindings in which the named object appears as either the _subject_ or the _observer_. Bindings deleted by **hook forget** will never be called again. In particular, * If an observer is forgotten during a call to **hook call**, any uncalled binding it might have had to the relevant subject and hook will **not** be called subsequently. * If a subject $s is forgotten during a call to **hook call $s $h**, **hook call** will return as soon as the current binding returns. No further bindings will be called. ## Configuration Subcommands > **hook cget** _option_ This command returns the value of one of the **hook** command's configuration options. > **hook configure** _option value_ ... This command sets the value of one or more of the **hook** command's configuration options: -errorcommand: If the value of this option is the empty string, "", then errors and other exception returns in binding scripts are propagated normally. Otherwise, it must be a command prefix taking three additional arguments: a list \{_subject hook arglist observer_\}, the result string, and the return options dictionary. Given this information, the **-errorcommand** can choose to log the error, call **interp bgerror**, delete the errant binding \(thus preventing the error from arising a second time\) and so forth. -tracecommand: The option's value should be a command prefix taking four arguments: a _subject_, a _hook_, a list of the hook's _argument values_, and a list of _objects_ the hook. The command will be called for each hook that is called. This allows the application to trace hook execution for debugging purposes. # Example The ::model module calls the <Update> hook in response to commands that change the model's data: hook call ::model <Update> The .view megawidget displays the model state, and needs to know about model updates. Consequently, it subscribes to the ::model's <Update> hook. hook bind ::model <Update> .view [list .view ModelUpdate] When the ::model calls the hook, the .view's ModelUpdate subcommand will be called. Later the .view megawidget is destroyed. In its destructor, it tells the **hook** that it no longer exists: hook forget .view All bindings involving .view are deleted. # Possible Additions During discussions on the tcl-core mailing list, members suggested a number of possible additions to the functionality described in the first draft of this TIP. Some small capabilities have been added in this draft; however, there are two significant ones that I have elected to defer, for two reasons: * Though reasonable additions, they are somewhat orthogonal to the functionality provided here. * They are somewhat speculative, as they reflect patterns I've not actually used, whereas the functionality described above has been in use in real applications for the past five years. Consequently, I'd rather not delay this TIP until these suggested additions are mature. If this TIP is accepted, then these additions can be considered as TIPs in their own right. On the other hand, they are genuinely interesting, so I want to mention them here. ## Asynchronous Dispatch The **hook call** command calls bindings synchronously, returning after all bindings have been called. An asychronous mode has been proposed, where bindings would be called in the context of the event loop for even looser coupling between the subject and the observers. This is certainly doable; however, the same effect can be achieved by calling **hook call** in an **after** handler. I've often considered adding a mode like this to our existing implementation, but have always thought better of it in the end. ## Accumulating Binding Return Values Two members of tcl-core have suggested that **hook call** would be useful to support plug-in architectures if the return values of all bindings called were properly captured. This is an interesting notion; but I'm not sure how to get it right. In some use cases, it would be enough just to get a list of the return values. In other uses cases, the caller might want to know the observer, the return value, and the complete dictionary of return options. I don't want to build up all of this return information in the usual case; if it isn't needed, there's no reason to spend the time accumulating it. Consequently, what makes sense to me is an option or options that determine what kind of information should be returned, e.g., **hook call ?options...? $s $h ...** Given that **hook call** currently returns the empty string, this functionality can easily be added at a later time. # Prototype Implementation A prototype implementation is available at <http://www.wjduquette.com/notifier/hook-0.1.zip> . It is written in Tcl. The prototype implementation should work in both Tcl 8.5 and Tcl 8.6. # Copyright This document has been placed in the public domain. |
Name change from tip/38.tip to tip/38.md.
|
| < | < | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 38: Add Support for Default Bindtags Author: Bryan Oakley <[email protected]> State: Withdrawn Type: Project Vote: Pending Created: 27-Jun-2001 Tcl-Version: 8.5 Post-History: ----- # Abstract This TIP proposes to add support for the ability to change the default list of bindtags for a class of widgets. # Introduction Bindtags are an extremely useful addition to the Tk toolkit. By modifying the bindtags for a given widget, enhanced bindings can be added, or default behaviors removed, without modifying actual bindings. At present, the default bindtags for a widget are fixed. All widgets are created with the same default bindtags. If an application programmer wants to alter the bindtags for a widget, she must do so on a case by case basis. By allowing the programmer to define their own default bindtags, one can leverage the power of bindtags with fewer lines of code. In addition, changing the default bindtags can not only affect all widgets in a block of code, but widgets that are created at runtime, even if created by imported packages that are beyond the programmer's control. # Specification An enhancement to the bindtags command is suggested. At present, the only valid use of bindtags is to include a widget name as the first argument. Therefore, adding a new parameter that does not begin with a dot will not break any existing scripts \(that is to say, any script that presently has the command _bindtags default_ is broken\). This TIP proposes the following enhancement to the bindtags syntax: bindtags default class tagList _default_ is the literal name of a subcommand _class_ is a widget class \(e.g. Listbox, Text, etc\) or _\*_ to signify all classes. A default for a specific class will override the default for all. _tagList_ is a Tcl list of bindtags, with support for the following meta-characters, ala bind: %C: the widget class %W: the widget path for a specific instance of a widget %%: replaced with a single % For example: bindtags default Text [list Special %W %C . all] => Special %W %C . all text .t => .t bindtags .t => Special .t Text . all If _tagList_ is null \(e.g. _bindtags default Text \{\}_\), the default bindtag reverts to the existing behavior. Because of this it is not possible to associate a null bindtag list to a widget, but it's doubtful that would ever be an issue. One could just as easily associate a bogus bindtag that has no bindings to get the same result. \(As an alternate suggestion, we could allow null bindtag lists, and use _bindtags default Text_ without a tagList to specify that the core defaults be used\). When a widget is created, its default bindtags will be those specified by the programmer via the enhanced syntax. If no defaults have been specified, the current behavior will be used. For widgets that take a -class parameter \(e.g. frames\), it will choose the bindtags based on its requested class rather than its base class. For example, _frame .foo -class Combobox_ will use the bindtags for the class _Combobox_ rather than the class _Frame_. # Rationale Occasionally it is desirable to add a special bindtag to the front or end of the bindtag list for all widgets in an application. Or, one way want to replace the widget class bindtag with their own or remove it altogether. Without a way to specify a default, a programmer must issue a bindtag command for every widget after it is created. This has an impact on overall performance. In addition, it can be a source of errors over time; if a new programmer begins work on a project, she may not realize that widgets need this new bindtag and fail to add it in her code. In addition, when widgets are created dynamically during the course of a user's interaction with the system \(for example, when a dialog is created before it is popped up\), the bindtags must be added at runtime. Often this is impractical if the dialog or widget\(s\) belong to an imported package that the programmer can't modify. # Alternatives to this TIP An alternative way to implement this TIP might be to modify each widget command such that it becomes configurable. An example might be: button configure -bindtags {Special %W %C . all} => Special %W %C . all button .foo => .foo bindtags .foo Special .foo Button . all Given that the widget commands now have no notion of class-level configuration values, it seems awkward to introduce it at this time. It would, however, open up the door for adding other features in future versions of Tk. I can envision, for example, _button configure -renderer myButtonRenderProc_, which would call myButtonRenderProc to render button widgets instead of using the default C-based renderer. This might make it possible to support a pluggable look and feel some day. Keeping all of the bindtags interaction with the bindtags command seems like a better way to go. # Notice of Withdrawal This TIP was Withdrawn by the TIP Editor following discussion on the tcl-core mailing list. The following is a summary of reasons for withdrawal: > Perhaps some of the ideas behind these TIPs should be incorporated into some new TIP on making megawidget support better, but none of these TIPs really stand on their own. \(38 isn't a good idea, since alteration of the bindtags for all widgets of a class at once is a bad idea, and it is better when rolling your own megawidget classes to put the setting up of the bindtags in there. 39 and 42 just clash with each other as soon as you have two different codebases trying to use a single widget.\) # Copyright This document has been placed in the public domain with great vigor. |
Name change from tip/380.tip to tip/380.md.
|
| < | | | | | | < | | > | | | | | | | | | | | | | | | | | | | | < > | | | < > | | < > | | | | | < > | < > | | < | > | | | | | | | | | | | | > | 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 | # TIP 380: TclOO Slots for Flexible Declarations State: Final Type: Project Tcl-Version: 8.6 Vote: Done Post-History: Author: Donal K. Fellows <[email protected]> Created: 20-Oct-2010 ----- # Abstract This TIP proposes a system that enables a more flexible system of handling all declarations relating to classes and objects that resolve to control over a list of things. This system, which will use TclOO to configure itself, will enable the scripting of additional mechanisms for manipulating declarations and will also include a change to the default behavior of the **filter** and **variable** declarations, where the standard "replace everything" behavior was found to be non-obvious in practice. In order to enable this, the exact behavior of the **unknown** method mechanism will be slightly varied. # Rationale Substantial deployment experience with TclOO now exists, and one of the things that has been consistently found to be surprising has been the way that the **variable** declaration \(part of **oo::define** and **oo::objdefine**\) replaces the current list of declared variables. Personal experimentation has indicated that the **filter** declaration is just as surprising, though it is admittedly less frequently used. Therefore it is desirable to alter the way such declarations work so that they append to the list of variables \(or filters, depending on what is being declared\). However, if this is being done then there is a need for substantial complexity to be added; there must be _some_ way to set the list of things being declared or clear it as well as appending to it. Moreover, at the base level both **superclass** and **mixin** declarations are basically the same structure; a list of things. For moral consistency, it becomes necessary to apply the same basic rules there, though with different defaults; in practice the default "replace" rule is suitable in for both those two cases. Note that for the declarations not mentioned, their natural model is not that of a list so there is no underlying unity of declaration system possible at this level. They will be left unchanged by this TIP. # Proposed Change My proposed solution is the introduction of a new standard class, **::oo::Slot**, whose instances will provide configuration services to the **oo::define** and **oo::objdefine** commands. The proposed definition of the class will be this: oo::define oo::Slot { method Get {} {error unimplemented} method Set list {error unimplemented} method --default-operation args {error unimplemented} method -set args { tailcall my Set $args } method -append args { tailcall my Set [list \ {*}[uplevel 1 [list [namespace which my] Get]] {*}$args] } method -clear {} { tailcall my Set {} } method unknown {args} { if {[llength $args] == 0} { tailcall my --default-operation } elseif {![string match -* [lindex $args 0]]} { tailcall my --default-operation {*}$args } next {*}$args } export -set -append -clear unexport unknown destroy } It will be up to the instances \(whose names do _not_ form part of this specification\) to define appropriate interpretations for the **Get**, **Set** and **--default-operation** methods, with the last being envisaged as an ideal fit for being done by one of the other methods, with the connection being made by **forward**. In order to enable this, a small change is required to the **unknown** method mechanism. This change is that in the case that there is no method name at all passed to a call into an object, that will have to be handled by passing into the unknown method mechanism. This will only have a significant impact on declarations of the **unknown** method where the formal argument list was _args_; in the other cases there is typically a required first formal argument and that leads under the current implementation of methods to the same error message as currently defined. Since this is a rare case of a rarely used mechanism, I judge that this is likely to be an acceptable semantic change. The real major change here is that for certain things \(i.e., **variable**, **superclass**, **mixin** and **filter** declarations\) it becomes trickier to use these with named things whose names start with a "-" character. I believe this to be a reasonable and minimal trade-off, given that in return we are getting more natural usage for many users while maintaining a standard mechanism for a whole way of handling declarations. # Reference Implementation See SF Patch \#3084339 <https://sourceforge.net/support/tracker.php?aid=3084339> # Copyright This document has been placed in the public domain. |
Name change from tip/381.tip to tip/381.md.
|
| < | | | | | | < | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 381: Call Chain Introspection and Control State: Final Type: Project Tcl-Version: 8.6 Vote: Done Post-History: Author: Donal K. Fellows <[email protected]> Created: 20-Oct-2010 Keywords: TclOO, iTcl ----- # Abstract This TIP proposes mechanisms for inspecting the TclOO call chain for a particular method, both externally via **info** and from within a call to that method. It also proposes a mechanism that will allow the traversal of the call chain in a more controlled way than at present with the **next** command. # Rationale Experience with TclOO in deployment has shown that the call chain mechanism used for identifying method implementations to bind to a particular method call is not just a powerful system, but also fairly difficult to understand. In particular, there is currently no way to discover what implementations of a method will be actually called, which makes debugging more difficult than it ought to be. In addition, it has been found that it is quite difficult to manage multiple inheritance with TclOO. In particular, when a "diamond" inheritance graph is constructed where the different arms of the graph require different arguments, it is exceptionally difficult to ensure that the correct arguments get delivered to the right constructors, this being a requirement for some of the ways in which people use [incr Tcl] and build megawidgets. Arguably, in these cases it would be perhaps better for code to use delegation as a class composition mechanism, but it is not the place of TclOO to impose such a policy. As such, there needs to be a mechanism to allow more precise runtime control over the traversal of call chain \(control over the construction of the chain would not be so useful; there simply is no right order that can ensure that immiscible constructor arguments get passed correctly\). # Proposed Changes There will be the the following subcommands of **info** added: > **info object call** _objectName methodName_ This will return a list describing the methods used to implement a call to the given _methodName_ on the given _objectName_. It will be an error to call it on anything that is not an object, but in the case that _methodName_ does not describe a \(visible\) method, the returned list will describe how things are handled by **unknown** processing. Each element of the list will be a tuple. The first element of the tuple will be one of **filter**, **method** and **unknown** to indicate whether it is a filter, a normal method call, or a special method call used to handle unknown methods \(i.e., with the method name as an additional argument\); the remainder of the tuple's interpretation will depend on which it is. The second element will be the name of the method implementation \(always **unknown** in the case of unknown handling, except where that is intercepted by a filter\). The third element will be the literal **object** or the fully-qualified name of the class of that provided the implementation of the method or filter \(NB: not necessarily the class that enabled the filtering through that name\). The fourth element will be the type of the method implementation \(i.e., as described by **info object methodtype** or **info class methodtype**, depending on where the method is declared\). > **info class call** _className methodName_ This will be similar to **info object call**, but will instead describe what would happen with a stereotypical instance of _className_. In addition, there will be an extra subcommand of **self**: > **self call** This will return a list of two items, the first being the list that would have been returned by **info object call** for this method call, and the second being an index into the list of the current method \(i.e., **0** for the first implementation on the list\). Finally, there will be another command made available inside method bodies to provide the advanced chain calling described above: > **nextto** _className_ ?_arg ..._? This command will behave just like **next** except that it will scan _forward_ in the current method chain until the implementation of the method provided by _className_ is located, and chain to that \(while passing in the _arg_uments given, of course\). It will be an error to attempt to call a class's implementation of a method that is not on the chain, or that is preceding the currently executing method implementation, and it will not be possible to jump to filters applied to the method. # Reference Implementation See <https://core.tcl.tk/tcloo/timeline?r=development-next2> for the proposed implementation \(notably commit-f5a2cfd0d4\). # Copyright This document has been placed in the public domain. |
Name change from tip/382.tip to tip/382.md.
|
| < | < | | | | | | | | | > | | | | | | | | | | | | | | | | > | 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 | # TIP 382: Let tk_getSaveFile ignore file overwrites Author: Pawel Salawa <[email protected]> Author: Don Porter <[email protected]> State: Final Type: Project Tcl-Version: 8.5.11 Vote: Done Created: 02-Nov-2010 Post-History: Keywords: Tk, dialog ----- # Abstract This document describes new option for **tk\_getSaveFile** named **-confirmoverwrite** to control whether a warning dialog is displayed when selecting an existing file for overwriting. # Rationale There's been numerous requests for support for file dialog that allows to select a file name with no matter if it exists or not. One workaround was to use **ttk::getAppendFile** from <http://wiki.tcl.tk/15897,> but it used its own file dialog, instead of native one. This TIP makes use of native file dialog. # Specification The **tk\_getSaveFile** will accept a **-confirmoverwrite** option with boolean value as its argument. Default value for this option is "**true**". If value for this option is "**false**", then the dialog won't warn user in case he selects existing file, that he's about to overwrite the file. The option will be supported only for **tk\_getSaveFile**, not for **tk\_getOpenFile**. A non-boolean value for this option will raise an error. The new option will be recognized and accepted on all platforms. For any platform where the underlying windowing system does not permit the required configuration, the option will have no effect, and the platform dialog will just do what it does. # Compatibility Default value matches existing behavior. # Reference Implementation See the **tip-382** branch. It includes implementations for X, supported Windows, and OSX Carbon. The proposed option will not be implemented for Pre-NT Windows. An implementation for OSX Cocoa may be possible using the approach outlined at <http://stackoverflow.com/questions/1930352/nssavepanel-squelching-the-confirm-replace-dialog/2390780#2390780> , but no such implementation is yet completed. # Copyright This document has been placed in the public domain. |
Name change from tip/383.tip to tip/383.md.
|
| < | < | | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 383: Injecting Code into Suspended Coroutines Author: Alexandre Ferrieux <[email protected]> Author: Miguel Sofer <[email protected]> State: Draft Type: Project Vote: Pending Created: 03-Dec-2010 Post-History: Keywords: debugging,coroutine,yielded Tcl-Version: 8.7 ----- # Abstract This proposes a new command, **coroinject**, that allows a programmer to inject arbitrary code into a suspended coroutine, for execution on next resumption. # Rationale When debugging complex coroutines - with many yield points and possibly rich state in local variables - sometimes one would like to inspect their state "from the outside", i.e., at a point where they are suspended. A typical situation is that of a big, single-threaded, event\+coro system, where the coro happily enables/disables fileevents along its life, and the fileevents are one way to resume the coro. At a given point \(bug\), things get stalled, with the fileevents disabled. The obvious questions are: 1. "where" is the coro \(at which yield site\)? and 2. what are the values of its local variables? Both these questions can be answered with the new **coroinject** primitive. The idea is to force a resumption of the coro along with an "immediate execution of extra code" directive, where the extra code says "dump the call stack with **info level** and **info frame**", or "dump the locals", etc. Another use would be to inject "**return -code return**", as an alternative to renaming to \{\} for terminating the coro in a way that respects its **catch**/**finally** termination handlers. Alternatively, returning with an error code will have the effect of gathering call stack information in the **-errorstack** options dictionary entry. At the other end of the spectrum, the injected code can be completely transparent: either with a forced resumption and injected code ending with **yield**, or merely waiting for normal resumption when the app sees fit, and injected code falling back to normal coro code. Note that the feature is similar to a proc-entry trace, but coroutine resumption is not currently a trace target. Also, it is an intrinsically "one-shot" mechanism, which makes it a better fit for its debugging purposes. # Definition The new command > **coroinject** _coroname_ _cmd_ ?_arg1 ..._? prepends to the code to be executed on resumption of the currently suspended coroutine, _coroname_, the following code: > _cmd_ _arg1..._ _resumearg_ where _resumearg_ is the single argument passed to the resumption command _coroname_. In turn, the result from the execution of _cmd_ will be seen by the coroutine's code as the result of **yield**. Note that: 1. Resumption itself must be done separately, by calling _coroname_ later, 2. If **coroinject** is called several times on the same _coroname_ before resuming it, the commands pile up in LIFO order. 3. In combination, the appending of _resumearg_ and the use of the result of _cmd_ to provide the result of **yield**, will allow the following style of fully transparent injection: proc probe {x y resumearg} {do things $x $y;return $resumearg} coroinject C probe foo bar # Naming Of course, the proposed **coroinject** is a placeholder for a suitable name. Alternatives that also make sense are: **::tcl::coroinject** and **interp coroinject**. Constructive bikeshedding welcome. # Reference Implementation The current **::tcl::unsupported::inject** implements most of the functionality described here, minus the _resumearg_ passing. It will be updated to include it if consensus gathers on this style. # Copyright This document has been placed in the public domain. |
Name change from tip/384.tip to tip/384.md.
|
| < | < | | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 384: Add File Alteration Monitoring to the Tcl Core Author: Reinhard Max <[email protected]> Author: Gerald W. Lester <[email protected]> State: Draft Type: Project Vote: Pending Created: 02-Dec-2010 Post-History: Keywords: kqueue,inotify,dnotify,gamin,FSevents,fam Tcl-Version: 8.7 ----- # Abstract This TIP proposes to add capabilities for monitoring changes in the file system to the Tcl core. # Rationale Most, if not all, platforms supported by Tcl today allow user space processes to monitor the file system for certain changes such as the creation, deletion, alteration or renaming of files. Unfortunately there is no unique cross-platform API for this, so a Tcl core feature will have to be backed by a series of platform-dependent implementations and possibly a fallback for platforms that don't have these monitoring capabilities or instances on which they have been disabled. Platform-specific APIs which should be supported by the final implementation \(list to be extended\): * inotify<http://en.wikipedia.org/wiki/Inotify> \(Linux\) * kqueue<http://en.wikipedia.org/wiki/Kqueue> \(BSD\) * FSEvents<http://en.wikipedia.org/wiki/FSEvents> \(Mac OS X\) * TWAPI <http://twapi.magicsplat.com/disk.html#begin_filesystem_monitor> \(Windows\) # Proposal A new subcommand should get added to the **file** command with the following syntax: > **file monitor** _path_ _callback_ ?_filter_? This will register _callback_ to be called from the event loop when one of the events specified by _filter_ occurs to the file or directory specified by _path_. Calling **file monitor** with an empty callback argument removes an existing callback from the given path. The calling conventions for _callback_ and the syntax of _filter_ are yet to be determined. # Rejected Alternatives The **file** command was chosen over **fileevent** and **chan event**, because the object to be monitored is passed by name and not as an open channel. As an API, FAM<http://en.wikipedia.org/wiki/File_alteration_monitor> would have been a more portable alternative, but it requres a daemon to be running on the local machine and it requires linking against a lib that is licensed under the LGPL. It might be possible to support FAM as a compile time alternative to the system's native notification method. There exists a serverless implementation of a subset of the FAM API, called Gamin<http://people.gnome.org/~veillard/gamin/index.html> , but that's also licensed under the LGPL. There exists a Tcl extension for inotify<https://sourceforge.net/projects/tcl-inotify/> , but it is licensed under the GPL and it's script level API is too close to the inotify primitives to serve as the basis of a cross-platform abstraction for such notifications. But it might be a good base for a scripted prototype to sort out the remaining details of the proposed script level API. # Further Ideas It might be an option to release the C code that unifies the various OS speciffic mechanisms under a single API as a separate library, so that projects other than Tcl can use it as well. # Copyright This document has been placed in the public domain. |
Name change from tip/385.tip to tip/385.md.
|
| < | < | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | < > | | | < | > | | | | | | < > | < > | | | | < > | < | > | | | | > | 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 | # TIP 385: Functional Traces On Variables Author: Alexandre Ferrieux <[email protected]> State: Draft Type: Project Vote: Pending Created: 13-Feb-2011 Post-History: Keywords: Tcl, traces Tcl-Version: 9.0 ----- # Abstract Functional traces are new variants of variable traces, that rely purely on value passing rather than variable updating. Applied to array traces, they allow a much more efficient implementation of various storage backends. # Rationale The current variable trace API does not focus on the read or written value; instead, only the variable \(and array key\) name is made available to the callback. Actual manipulation of the value thus involves updating the variable within the trace callback: the new, "synthetic" value must be written for real. While this approach is acceptable for a scalar variable, in the case of arrays it forces the "memoize" pattern: whenever reads are done on an array with a read trace, the read value is actually stored in the array, with no obvious spot to unset it afterwards. Hence, although we are backing the array with a function which is called on every read, the memory usage is that of a memoized function; this does not scale up at all. A typical situation where this matters, is the use of traces to wrap the convenient array syntax around another kind of storage \(like a pre-existing dictionary or database\): what is intended is that **$a\($x\)** becomes syntactic sugar for **[dict get $d $x]**, but without duplicating the storage in the array. This is currently impossible. The proposed extension to the trace API allows for "functional" traces, in the usual computing sense of "no side effect": here the value of interest is passed as an argument to a write trace callback, and taken from the return value of a read trace callback. This way, no access to the underlying variable is needed. The array syntax can become a frontend to just about anything, without any memory consumption, and with adequate preformance since values are passed as _Tcl\_Obj_s. Thus functional traces could also be named "virtual variables". As an extra bonus, "read-only variables" can be implemented efficiently, which is notably impossible with the current API \(since the write trace is called after the fact, it must rely on another mechanism to retrieve the pre-write value\). # Definition The new subcommands > **trace add variable** _name_ **readf** _cmdprefix_ > **trace add variable** _name_ **writef** _cmdprefix_ > **trace add variable** _name_ **unsetf** _cmdprefix_ > **trace add variable** _name_ **existsf** _cmdprefix_ are the functional variants of the existing **read**, **write**, and **unset** variable traces. The new **existsf** is made possible by the functional style. The _cmdprefix_ callback API is close to that of current traces, with two variations: 1. For a **readf** or **existsf** trace, the callback's returned value is used as the result of the read/exists operation. 2. For a **writef** trace, the value to be written is passed as an extra argument to the callback: > _cmdprefix_ _name1_ _name2_ **writef** _value_ In both cases, the value is passed efficiently as a **Tcl\_Obj**. # Demos Here is the full code exposing a dict as an array: trace add variable a readf [list trdictget ::d] trace add variable a writef [list trdictset ::d] proc trdictget {vv n1 n2 op} { upvar $vv v return [dict get $v $n2] } proc trdictset {vv n1 n2 op x} { upvar $vv v dict set v $n2 $x } Another example with Pascal-like 1-based numeric indices into a list, with bound checking, disguised as array keys: trace add variable a readf [list trplistget ::l] trace add variable a writef [list trplistset ::l] proc trplistget {vv n1 n2 op} { upvar $vv v if {($n2<1) || ($n2>[llength $v])} { error "Index $n2 out of range for list $vv" } return [lindex $v [expr {$n2-1}]] } proc trplistset {vv n1 n2 op x} { upvar $vv v if {($n2<1) || ($n2>[llength $v])} { error "Index $n2 out of range for list $vv" } lset v [expr {$n2-1}] $x } Obviously, the same principle can be applied to an SQLite or TDBC database; the net result is an instant-loadable "array". # Possible Extensions A natural generalization would be to hook into array-level operations like **size**, **names**, **get**, **unset**, **startSearch**, etc. But then, maybe an ensemble/oo API would be preferred \(hook one single command prefix for all operations concerning array _a_\). To be discussed. # Reference Implementation Coming soon. # Copyright This document has been placed in the public domain. |
Name change from tip/386.tip to tip/386.md.
|
| < | < | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 386: Relocation of Tcl/Tk Source Control Repositories Author: Kevin B. Kenny <[email protected]> Author: Kevin Kenny <[email protected]> State: Draft Type: Informative Vote: Pending Created: 01-Mar-2011 Post-History: Keywords: Fossil,DVCS ----- # Abstract This TIP describes the changed locations and procedures for source control for Tcl/Tk. # Background Earlier this year, SourceForge's CVS repositories were attacked by parties unknown, resulting in an outage of several weeks' duration. Although all data were eventually recovered, the aftermath of the attack and outage was that SourceForge staff have formally designated CVS hosting to be a legacy product and offered assistance with migration to Subversion. Since for some time the Tcl/Tk maintainers have wanted to transfer the version control repository to a distributed version control system \(DVCS\), the decision has been made to abandon SourceForge and adopt a Fossil repository. A donor who wishes to remain anonymous has given a reasonably powerful machine, **core.tcl.tk** to the Tcl Community Association and is providing rack space and bandwidth. The donor has also generously offered to make free shell accounts to qualified Tcl/Tk developers for CPU- and bandwidth-intensive tasks such as performance analysis and memory management audits. Interested developers should contact one of the TCT members listed at the end of this document. Needless to say, given the distributed nature of Fossil, we expect several mirrors to emerge; Richard Hipp of SQLite.org has provided the first one, appropriately named **mirror1.tcl.tk**. # Repository Locations The code base for Tcl itself now resides in a Fossil repository at <http://core.tcl.tk/tcl/> . The Fossil repository is available for anonymous cloning and for examination of version control history. At present, the bug tracker is disabled. Similarly, the code base for Tk resides at <http://core.tcl.tk/tk> . Tcl and Tk developers shall be granted 'push' rights to the respective repositories. Developers who are unfamiliar with Fossil are strongly encouraged to consult the documentation at <http://fossil-scm.org/> , in particular, the 'Fossil Concepts' paper at <http://fossil-scm.org/index.html/doc/trunk/www/concepts.wiki> . Novices to Fossil may want to work at least temporarily in 'autosync mode', which allows a CVS-like workflow. At present, the bug, feature request and patch trackers will remain on SourceForge. Any developer hosting a mirror is expected to disable the bug tracker \(it suffices to remove 't' permission from the 'anonymous' user\). At some point we may use a SourceForge-to-Fossil converter for the existing trackers, and we do not wish to worry about trying to keep SourceForge and Fossil in sync. **mirror1.tcl.tk** shall be kept up to date by a periodic automatic synchronization with **core.tcl.tk**. In order to avoid inadvertent forking, developers are requested not to push to mirrors unless **core.tcl.tk** suffers an extended outage. Before using a clone from a mirror, developers should verify that it copies the correct version of the repository at **core.tcl.tk**. This can be determined by examining the 'project ID', reported by the 'clone' operation. For Tcl, the ID should be 1ec9da4c469c29f4717e2a967fe6b916d9c8c06e and for Tk, it should be b5a34cc57b6712927bc5fd34ae98433a14c9fdea **UPDATE, June 2013** The ticket trackers have now also been migrated from SourceForge to **core.tcl.tk**. # Workflow Generally speaking, workflow will follow the description in <http://fossil-scm.org/index.html/doc/trunk/www/concepts.wiki#workflow> . It is expected that large projects will be conducted on named branches in the Fossil repository; in fact, such a project should most likely be commenced by committing to a branch in your local clone. If you do not wish to share your work with others, you may use a private branch, and Fossil will refrain from synchronizing it when you synchronize your clone. Simple bug fixes should be developed on the branch of the _earliest_ stable release that you intend to fix, and then merged forward onto the later releases' branches. It is expected that such "dovetail merges" will be frequent, so as to control the number of nuisance conflicts that will have to be resolved when merging. Questions about Fossil on the Tcl'ers Chat or in comp.lang.tcl are encouraged; it's essential that all Tcl/Tk developers develop at least some familiarity with the technology, and it's somewhat new to all of us! # Requesting access Tcl and Tk maintainers may request repository access by emailing one of the Tcl Core Team members on the following list: Joe English, Donal Fellows, Jeff Hobbs, Kevin Kenny, Andreas Kupries, Don Porter all of whom have the required access to add new users to core.tcl.tk. # Acknowledgments Major thanks are due to Roy Keene, for leading the migration effort, to Jörg Sonnenberger \(author of cvs2fossil\) and D. Richard Hipp \(author of fossil itself\) for many hours of unpaid support in getting the conversion to go, to Mark Janssen for developing scripts to audit the Fossil content against historical Tcl/Tk distributions, and to the many Tcl/Tk developers who tested and debugged the conversion process. # Copyright This document has been placed in the public domain. |
Name change from tip/387.tip to tip/387.md.
|
| < | | | | | | | | | < | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | < > | < | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 387: Unified Yield Command Syntax Author: Lars Hellström <[email protected]> State: Withdrawn Type: Project Vote: Pending Created: 30-May-2011 Tcl-Version: 8.6 Keywords: Tcl, coroutine Obsoleted-By: 396 Post-History: ----- # Abstract This document describes the _syntax_ of a unified **yield** command, which is designed so that it can combine all features of the various yield-related commands proposed during 2010. ## Note This should not be taken as a proposal to necessarily provide all the mentioned features right now, but rather as a roadmap to make a command into which they _could_ all be fitted. The purpose is to avoid choosing a direction that would get really awkward in the future. # General Considerations It is accepted as given that the present syntax of the **yield** command, namely > **yield** ?_value_? should continue to be valid. It is also desirable to control all additional features through options placed before the _value_, since that makes it possible to let an **interp alias** supply them. What is important given those constraints is that one must be able to determine whether the final argument is a _value_ or not solely from looking at the previous arguments, since any option name is also a perfectly valid _value_ for **yield** to return to the coroutine-caller. This can be accomplished through the rule that every option must consist of at least two words \(typically -name and value\); a word after an option is then known to be the _value_ if it is the very last word of the command, and known to be the first word of another option if it not the very last word of the command. \(By contrast, an attempt to get by with a **--** end-of-options option would become very complicated and error-prone.\) The overall command syntax would thus be similar to that of **return** \(options before an optional value\), although there is no need to reproduce any of return's options in **yield**, as all such functionality can be attained by yielding to **return**. # Possible Options We identify the following options: **-arguments**, **-delivery** and **-to**. These are described below: ## Argument Specifiers The option > **-arguments** _argspec_ would be used to specify a **proc**-style list of arguments for the coroutine-command. As mentioned in [[372]](372.md), **yieldm** can then be defined as: interp alias {} yieldm {} yield -arguments args whereas the default for **-arguments** is **\{arg ""\}**, as: yield -arguments {{arg ""}} explicitly says the coroutine-command should have one optional argument _arg_ with default value the empty string. The idea is that if the arguments supplied to the coroutine-command do not match the _argspec_, then the coroutine-command should throw an appropriate error rather than resuming the coroutine. In that case, the coroutine state does not change, and in particular the coroutine-command continues to use the same _argspec_. For the purpose of further discussion below, the elements in the _argspec_ list will be called **formal parameters** of the coroutine-command. ## Yielding To The **-to** option provides the functionality of the **yieldto** command, and has the syntax: > **-to** _cmdname_ ?_arg ..._? always absorbing all remaining arguments of the **yield** command; a precedent for this may be found in for example the **-join** option of the **glob** command. In order to meet the "at least two words" requirement for **yield** options, the _cmdname_ argument is mandatory, but this is quite natural since it is anyway to be resolved already by **yield**. Note that behavior like yielding and throwing an error can be performed by yielding to **return**: yield -to return -code error -errorcode DEMO "Just an example" **-code** and **-errorcode** here are not options of **yield**, but of **return**, although the impression is probably close to that of having them options of **yield** directly. ## Argument Delivery An issue where no obvious solution presented itself was that of how arguments supplied to the coroutine-command should be made available in the coroutine. This proposal suggest that a **-delivery** option could be used to control this, and that the word after **-delivery** is a _mode_ keyword which selects whether the arguments should be provided as a list, a dictionary, in variables, or whatever. The following is a list of possible forms of this option. The supported modes will be one of: **dict**, **first**, **flat**, **same** and **vars**. These are described below. \(Note that different modes need not have the same number of argument words.\) ### Dictionary Delivery > **-delivery dict** The return value of **yield** is a dictionary, with one entry for each formal parameter, the entries appearing in the same order as in the **-arguments** _argspec_, and the values filled in as they would be for a **proc** call. The latter implies that _default values are filled in for missing optional arguments_; this preserves the invariant for the caller that specifying the default value for an optional argument is the same as omitting that argument. Thus, for the demonstration code: proc demo {delivery} { set last "" foreach argspec { foo {{arg ""}} {{arg ""}} args {foo args} } { set last [yield -arguments $argspec -delivery $delivery $last] } return $last } one can get this interactive session: % coroutine C demo dict % C "a b" foo {a b} % C "a b" arg {a b} % C arg {} % C "a b" args {{a b}} % C "a b" foo {a b} args {} ### Flat Delivery It is not unreasonable to also expect a mode that delivers just the list of formal parameter values, e.g. > **-delivery list** but this can be obtained from dict values [yield -delivery dict ...] since the **dict** mode is specified as putting the entries in the right order. Instead there is another take on returning a list of arguments that provides extra functionality: > **-delivery flat** The return value of **yield** is the list of arguments of the coroutine-command, regardless of **-arguments** _argspec_. This is the **yield** counterpart of **info level 0**, providing full introspection into the arguments, but also leaving parsing entirely up to the programmer. With the same sequence of calls as above, one gets % coroutine C demo flat % C "a b" {a b} % C "a b" {a b} % C % C "a b" {a b} % C "a b" {a b} ### Delivery to Local Variables > **-delivery vars** _varlist_ The _varlist_ must be a list with one element for each formal parameter. The values of the formal parameters are assigned, in sequence, to the variables named in the _varlist_. The return value is an empty string. Of course, most of the time one would use the same names as in the _argspec_, so it is reasonable to have a shorthand for this: > **-delivery same** The main reason to do otherwise is if both the procedure **yield**ing and the coroutine-command has an **args** argument, since that is a magical name. Hiding implementation details from users can also be a reason to specify a different _varlist_. A further possibility that has been suggested would be: > **-delivery array** _arrname_ for dumping the arguments as entries in an array. This can however be accomplished through array set $arrname [yield -delivery dict ...] which is probably easy enough. ### Simple Delivery Finally, there is: > **-delivery first** The return value is the value of the first formal parameter, or an empty string if there are no formal parameters; values of additional formal parameters are discarded. _This is the default._ This may seem a strange mode of delivery, and an even stranger thing to have as default, but it is what one must have if the [[372]](372.md) examples of varying the _argspec_ should work as claimed there. With the same demo as before, one gets: % coroutine C demo first % C "a b" ; # -arguments foo a b % C "a b" ; # -arguments {{arg ""}} a b % C ; # -arguments {{arg ""}} % C "a b" ; # -arguments args {a b} % C "a b" ; # -arguments {foo args} a b An alternative which is perhaps more convenient, but also more complicated, is to have the default **-delivery** depend on the number of formal parameters. It is then likely that one for the case of more than one formal parameter would want Yet Another delivery mode... # Reference Implementation None yet. # Other Commands If coroutines are going to have **proc**-style argspecs, then it will probably make sense for **info args** and **info default** to operate on coroutine-commands as well as procedures. # Acknowledgements This TIP is dedicated to Alexandre Ferrieux, who's known to have written that I should prioritize TIPping things over participating in tcl-core discussions. ;-\) # Copyright This document has been placed in the public domain. |
Name change from tip/388.tip to tip/388.md.
|
| < | < | | | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 388: Extending Unicode literals past the BMP Author: Jan Nijtmans <[email protected]> Author: Jan Nijtmans <[email protected]> State: Final Type: Project Vote: Done Created: 10-Aug-2011 Post-History: Discussions-To: Tcl Core list Keywords: Tcl Tcl-Version: 8.6 ----- # Abstract This TIP proposes to extend Tcl's syntax in order to be able to cope with quoted forms of Unicode characters outside the Basic Multilingual Plane. # Summary Tcl provides backslash substitutions of the form **\\uhhhh** for unicode characters, but this form is not sufficient to model unicode literals past the BMP. The outcome of the discussion on Tcl-Core was to add the form **\\Uhhhhhhhh** \(one up to 8 hexadecimal digits\), but still it is ambiguous how characters > 0x10ffff are to be handled. This TIP is meant to sort that out, it is not meant to specify how characters outside the BMP are handled. The reference implementation just replaces any character in the range **\\U010000** - **\\U10ffff** with **\\ufffd**, but as soon as Tcl has support for characters outside the BMP this range is reserved for exactly that. Currently, the form **\\U** is parsed by Tcl as a literal **U**, so - however small - this change results in a non-trivial potential incompatibility which therefore requires a TIP. Considering backslash sequences, there are two other forms which are currently not consistent: **\\xhh** accepts an unlimited number of hex digits, unlike other modern languages, and the form **\\ooo**, where the first octal digit is in the range 4..7 is currently not handled consistently in Tcl. Now is an opportunity to reconsider this. In tcl.h there is a remark regarding the possible values of TCL\_UTF\_MAX: * 3 Currently the only supported value, defining Tcl\_UniChar as unsigned short * 6 Not supported, but reserved for a hypothetical 32-bit Unicode * 1 Not supported, possibly for a ASCII-only variant of Tcl. This document proposes to add another value: * 4 Not supported. The same as 3, but allowing the use of Unicode surrogate pairs to represent the range **\\U010000** - **\\U10ffff** # Rationale Consider the string **\\701**, how is that supposed to be interpreted? Tcl specifies octal sequences as 8 bits, and silently strips the 9th bit, the same as gcc does. In Tcl's regular expression engine, the 9th bit is not stripped, there it is equivalent to **\\u01c1**. Java - for example - parses it as **\\70** - a valid 8-bit octal value - followed by **1**, so it's a string of length 2. Then the string **\\x1234**. Tcl specifies this as 8 bits as well, and silently strips all higher bits, so it is equivalent to **\\u0034**. This is the same as gcc does, but Java - for example - considers it as **\\x12** followed by **34**, so it's a string of lenght 3. Consider the string **\\U00123456**, which would result in an invalid Unicode character. In the Tcl parser we don't have the possibility to flag invalid backslash sequences, in Tcl's regexp engine we have. Unicode characters higher than **\\U0010ffff** cannot appear in an UTF-8 stream. In tcl.h, we find Tcl\_UniChar to be defined as unsigned int when TCL\_UTF\_MAX > 3 and as unsigned short otherwise. It would be useful to reserve the value 4 and still define Tcl\_UniChar as unsigned short. That would allow the path to a full support for out-of BMP Unicode characters shorter, because Unicode Surrogate pairs can be used for that. # Specification This document proposes: * Change the parsers in Tcl to handle octal sequences higher than **\\377** differently, splitting it in a two-digit valid octal secuence and handling the additional character separately. So **\\701** is handled as the valid sequence **\\70** followed by **1**. This is a **potential incompatibility**. * Change the parsers in Tcl to handle the **\\xhh** sequence to parse just 2 digits, and not silently strip all higher hex digits any more. This is a **potential incompatibility**. * Add the **\\Uhhhhhhhh** handling, similar to the **\\uhhhh** handling, only accepting up to 8 characters. The parser will stop parsing earlier when a code point **\\U00011000** or higher is reached, as shifting it 4 bits more will lead to a code point outside the Unicode range. The regexp engine already handles **\\Uhhhhhhhh**, but currently it always generates a character in the BMP and strips all higher bits. This is a **potential incompatibility**. # Compatibility Tcl scripts using the form **\\ooo** where the first digit is in the range 4-7, will now interpred the string as **\\oo** followed by **o**. There is currently no test case in the Tcl test suite affected by that. Tcl scripts using the form **\\xhhh**, which used to strip off the higher digits, will now end the sequence when two digits are handled. Tcl scripts using **\\U** as a literal **U** will no longer work when it is followed with at least one hexadecimal digit. There is currently no test case in the Tcl test suite affected by that. # Alternatives Unicode Noncharacters or Surrogages are not supposed to be in an UTF-8 stream, the Unicode standard recommends to replace those with **\\ufffd**. This TIP does not propose that, because they may be used internally e.g. as part of a character range in a regular expression. A better place to do that is in the Utf8-To-Utf8 conversion, but that's outside the scope of this TIP. # Reference Implementation A reference implementation is available at <http://core.tcl.tk/tcl> in branch tip-388-impl # Copyright This document has been placed in the public domain. |
Name change from tip/389.tip to tip/389.md.
|
| < | < | | | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 389: Full support for Unicode 8.0 and later Author: Jan Nijtmans <[email protected]> Author: Jan Nijtmans <[email protected]> State: Draft Type: Project Vote: Pending Created: 23-Aug-2011 Post-History: Discussions-To: Tcl Core list Keywords: Tcl Tcl-Version: 8.7 ----- # Abstract This TIP proposes to add full support for all characters in Unicode 8.0\+, inclusive the characters >= **U\+010000**. # Summary In order to extend the range of the characters to more than 16 bits, the type _Tcl\_UniChar_ is not big enough any more to hold all possible characters. Changing the type of _Tcl\_UniChar_ to a 32-bit quantity is not an option, as it will result in a binary API incompatibility. The solution proposed in this TIP is to keep _Tcl\_UniChar_ a 16-bit quantity, but to increase the value of TCL\_UTF\_MAX to 4 \(from 3\). Any conversions from UTF-8 to _Tcl\_UniChar_ will convert any valid 4-byte UTF-8 sequence to a sequence of two Surrogate characters. All conversions from UTF-16 to UTF-8 will make sure that any High Surrogate immediately followed by a Low Surrogate will result in a single 4-byte UTF-8 character. This can be done in a binary compatible way: No source code of existing extensions need to be modified. As long as no characters >= **U\+010000** or Surrogates are used, all functions provided by the Tcl library will function as before. There are few functions which currently return a value of type _Tcl\_UniChar_, those will be modified to return an int in stead. # Rationale As Unicode 8.0, and future Unicode versions, will supply more and more characters outside the 16-bit range, it would be useful if Tcl supports that as well. # Specification This document proposes: * Change the functions _Tcl\_UniCharToUtf_ and _UnicodeToUtfProc_ such that when they are fed with a valid High Surrogate followed by a Low Surrogate, the result will be a single 4-byte UTF-8 character. * Change the functions _Tcl\_UtfToUniChar_ and _UtfToUnicodeProc_ such that when they are fed with a valid 4-byte UTF-8 character, the first call will return a High Surrogate character, and the next call will return a Low Surrogate character. * The following functions, which currently return a Tcl\_UniChar, will be changed to return an int instead: > \* _Tcl\_UniCharAtIndex_ > \* _Tcl\_UniCharToLower_ > \* _Tcl\_UniCharToTitle_ > \* _Tcl\_UniCharToUpper_ > \* _Tcl\_GetUniChar_ * Extend tclUniData.c to include all Unicode 8.0 characters up to **U\+02FA20**. A special case will be made for the functions _Tcl\_UniCharIsGraph_ and _Tcl\_UniCharIsPrint_ for the characters in the range **U\+0E0100** - **U\+0E01EF**, otherwise it would almost double the Unicode table size. # Compatibility As long as no Surrogates or characters >= **U\+010000** are used, all functions behave exactly the same as before. The only way that _Tcl\_UniCharToUtf_ can produce a 4-byte output is when Surrogates or characters >= **U\+010000** are used. Extension that want to be compatible with any Tcl version, can include tcl.h as follows: #define TCL_UTF_MAX 4 #include <tcl.h> or they can call the C compiler with the additional argument -DTCL\_UTF\_MAX=4, in order to be sure that UTF-8 representations of length 4 can be handled. This way, the extension can be used with any Tcl version, whether it supports Surrogates or not. Apart from this, it is advisable to initialize the variable where the chPtr argument from _Tcl\_UtfToUniChar_ points to, as this location is used to remember whether the High Surrogate is already produced or not. Not doing so when the first character of a string is a character > **U\+010000** might result in a Low Surrogate character only. This danger, however unlikely, only exists for the first character in a string, and it only occurs when the \(random\) value is exactly equal to the expected High Surrogate. # Reference Implementation A reference implementation is available at <http://core.tcl.tk/tcl> in branch tip-389-impl # Copyright This document has been placed in the public domain. |
Name change from tip/39.tip to tip/39.md.
|
| < | < | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 39: Add New Standard Tk Option: -component Author: Bryan Oakley <[email protected]> State: Withdrawn Type: Project Vote: Pending Created: 04-Jul-2001 Post-History: Keywords: compound,megawidget Tcl-Version: 8.5 ----- # Abstract This TIP proposes to add a new standard option, _-component_, for all Tk widgets. # Introduction One of the problems with creating compound widgets \(or "megawidgets"\) in Tk is library code that doesn't know whether a widget is a widget or whether it is merely a component of a larger compound widget. This TIP suggests a new common option for all widgets that defines whether a widget is merely a component of a larger compound object. The value of this option would normally be the empty string, but could be set to the name of a widget that is the "root" of a compound widget \(typically a component window's parent\). For example, consider a prototypical labelled entry widget that is made up of a frame \(.f\), and entry widget \(.f.e\) and a label \(.f.l\). These might be defined as follows: frame .f -class LabelledEntry entry .f.e -component .f label .f.l -component .f Internal commands that act upon widgets could use this information to alter their behavior for component widgets. For example, _tk\_focusNext_ and _tk\_focusPrev_ could ignore components when figuring out where to send focus, typically as a result of the user pressing <Tab> or <Shift-Tab>. This would help sole a nagging problem with many compound widgets. We might want to modify [winfo children] to ignore component windows as well \(unless, for example, _-showcomponents_ is set to true\), only reporting those children added by external entities. For example, consider a compound widget that implements a scrollable container. This widget might be built with a frame \(.f\), a vertical scrollbar \(.f.v\) and a horizontal scrollbar \(.f.h\). After a user adds their own widgets to this window they would expect [winfo children .f] to return only the windows they created, and might be confused \(or at least annoyed\) by the presence of these internal windows. # Specification Suggested wording for the _options_ man page: Command-Line Name: -component Database Name: component Database Class: Component > _Designates that this widget is a component of a larger widget. This option is normally the empty string. If it is not the empty string, it should be set to the "root" of the compound widget. For example, if a compound widget is made up of frame ".f" and an entry widget ".f.e", the latter will have as it's component value ".f" designating that it is a component of the compound widget rooted at ".f"_ In addition, _tk\_focusPrev_ and _tk\_focusNext_ should take the value of this flag into consideration when determining where focus should next be given \(i.e. it should not give focus to components; focus should be given to root widgets, which shall be responsible for redirecting focus as required\). Once this TIP gets implemented, subsequent TIPs can be produced to define how additional Tk library functions and commands can be modified to take advantage of this new information. # Rationale We need a standardized way of determining whether a widget is an atomic object or part of a larger compound object. This has several uses, the most obvious \(to me, anyway\) being focus management. # Notice of Withdrawal This TIP was Withdrawn by the TIP Editor following discussion on the tcl-core mailing list. The following is a summary of reasons for withdrawal: > Perhaps some of the ideas behind these TIPs should be incorporated into some new TIP on making megawidget support better, but none of these TIPs really stand on their own. \(38 isn't a good idea, since alteration of the bindtags for all widgets of a class at once is a bad idea, and it is better when rolling your own megawidget classes to put the setting up of the bindtags in there. 39 and 42 just clash with each other as soon as you have two different codebases trying to use a single widget.\) # Copyright This document has been placed in the public domain with unabashed hope for a brighter future. |
Name change from tip/390.tip to tip/390.md.
|
| < | | | | | | < | | > | | | | | | | | | | | | | | | < | > | | | | | | | | > | 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 | # TIP 390: A Logging API for Tcl Author: Jeff Rogers <[email protected]> State: Draft Type: Project Tcl-Version: 8.7 Created: 27-Oct-2011 Vote: Pending Post-History: ----- # Abstract This TIP proposes a standard API for logging in Tcl applications, both at the Tcl and C level. # Rationale Logging is needed in most applications. There is no standard, documented logging API in Tcl, for either Tcl or C code, leading most people to roll their own. The TIP proposes a standard Tcl and C API that handles the most common logging functions. The default implementation of the logger should just print the message \(with substitutions performed as if with **format**\) to the standard error channel. # Specification 1. **Tcl\_Log**\(_interp_, _level_, _message_, ...\) > This is the main C api call; it logs the formatted message at the specified loglevel. If interp is specified, it operates within the context of that interp; if NULL then it logs in a maner not associated with any interp. 2. **Tcl\_SetLogLevel**\(_interp_, _level_\) > Instructs the logging system to set the loglevel to the given value. Legal levels are TCL\_LOG\_DEV, TCL\_LOG\_DEBUG, TCL\_LOG\_INFO, TCL\_LOG\_NOTICE, TCL\_LOG\_WARNING, TCL\_LOG\_ERROR, TCL\_LOG\_FATAL, TCL\_LOG\_BUG 3. **Tcl\_SetLogHandler**\(_interp_, _logHandler_\) struct Tcl_LogHandler { Tcl_LogHandlerProc(interp, level, message, ...) Tcl_SetLogLevelProc(interp, level) } > Installs a new loghandler for a specified interp or globally. If no log handler is installed, the default action is to print the formatted message on standard error if the message level is equal to or greater than the loglevel; in the context of an interp the default action is to call the configured log handler \(which does the same thing by default\) 4. **interp logger** ?_loggerCommandFragment_? > Gets or sets the log handler for an interp. The log handler will have these arguments appended on invoke: _level message args_ 5. **log** _level message_ > Tcl equivalent of **Tcl\_Log**. # Copyright This document has been placed in the public domain. |
Name change from tip/391.tip to tip/391.md.
|
| < | | | | | | | < | | > | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 391: Support for UDP Sockets in Tcl Author: Jeff Rogers <[email protected]> State: Withdrawn Type: Project Tcl-Version: 8.7 Vote: Pending Created: 26-Oct-2011 Post-History: Obsoleted-By: 409 ----- # Abstract This proposal is to add UDP socket support to the core in a clean and unobtrusive way. # Rationale UDP is used for sending datagrams over the internet, which is an integral part of a number of protocols, notably including direct DNS queries in the majority of deployment. Thus, it is useful to be able have Tcl able to send and receive messages via UDP sockets, filling out a signficant missing feature. UDP sockets have the same basic needs as tcp sockets - creating, reading, writing. So it follows that they could be handled by the same basic commands. # Specification The **socket** command should have a flag, **-udp**, added. This should work for both client and server sockets. > **socket -udp** ?**-myaddr** _addr_? ?**-myport** _port_? _host port_ > **socket -udp -server** _command_ ?**-myaddr** _addr_? _port_ To complement this, the sockets created by the above commands will have an additional configuration option, **-peeraddr**. This is a read/write option. It is used to set the peer address before a write, and to retrieve the peer address after a read. The peer address should persist until it is changed by a read or fconfigure. When used on a UDP socket, **puts** sends a single message \(sendmsg\). If the data is too large to fit in a single message then an error is raised. When reading from a udp socket, the data retuend will only ever be the contents of a single message in a single operation. Thus, **read** will return one entire message, and **read** with a bytecount or **gets** will read a new message into their buffer iff it is completely empty, and will return the requested data from that buffer. Readable and writable fileevents should work naturally. # Example Usage set udpsock [socket -udp 8.8.8.8 53] fconfigure $udpsock -peeraddr {8.8.8.8 53} puts $udpsock $packet set packet [read $udpsock] set peer [fconfigure $udpsock -peeraddr] # Copyright This document has been placed in the public domain. |
Name change from tip/392.tip to tip/392.md.
|
| < | < | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 392: Allow Bignums to be Disabled at Runtime on a Per-Interp Basis Author: Joe Mistachkin <[email protected]> State: Draft Type: Project Vote: Pending Created: 30-Oct-2011 Keywords: bignum,runaway,safe,math,precision,integer,tcl Tcl-Version: 8.5 Post-History: ----- # Abstract This TIP proposes the ability to enable or disable all use of bignums at runtime on a per-interpreter basis. The mechanism being presented to accomplish this goal has been designed to be generic enough so that it can be used for other per-interpreter configuration parameters in the future. # Rationale As of Tcl version 8.5, almost any integer math calculation can result in bignums being used. Normally, this does not pose a serious problem; however, there are circumstances in which this can exhaust key system resources, such as memory or CPU time. Unlike other similar resource exhaustion problems, this one cannot be prevented by use of **interp create -safe**, **interp limit**, **interp cancel**, or similar mechanisms. If Tcl is being used in an embedding scenario, this has the potential to negatively impact the entire application or system. If Tcl is being used to evaluate marginally trusted or untrusted scripts in a safe interpreter, this can result in a denial-of-service \(DoS\) attack. # Specification A new **interp configure** script command will be added, as follows: > **interp configure** _path_ ?_name_? ?_value_? This command instructs Tcl to modify or query the value of the named configuration parameter _name_ in the interpreter identified by _path_. ## Arguments > _path_ This argument is required and specifies the interpreter to be reconfigured. An empty string may be used to indicate the current interpreter. > _name_ This argument is optional. If this argument is not supplied, the current list of configuration parameter names for the interpreter identified by _path_ will be returned. > _value_ This argument is optional. If this argument is not supplied, the current value of the named configuration parameter for the interpreter identified by _path_ will be returned; otherwise, the current value of the configuration parameter will be changed to the specified value. ## C API > Tcl\_Obj\* **Tcl\_InterpConfigure**\(Tcl\_Interp\* _interp_, Tcl\_Obj\* _nameObjPtr_, Tcl\_Obj\* _valueObjPtr_\) The **Tcl\_InterpConfigure** function gets or sets the named configuration parameter for the specified interpreter. The _nameObjPtr_, if not NULL, must be a string containing the name of a known configuration parameter; otherwise, NULL will be returned and the interpreter result will be modified to contain an appropriate error message. The _valueObjPtr_, if not NULL, must have a value convertible to the type required by the configuration parameter being set; otherwise, NULL will be returned and the interpreter result will be modified to contain an appropriate error message. If _valueObjPtr_ is NULL, the current value of the named configuration parameter will be returned instead of being changed. If _nameObjPtr_ is NULL, the complete list of known configuration parameter names will be returned. The caller is responsible for managing the reference count of the returned value. # Configuration Parameters Upon interpreter creation, all configuration parameters start with a default value. The default value for a configuration parameter is considered to be part of the formal interface. Initially, the only supported configuration parameter will be **bignums**. When setting the **bignums** configuration parameter, the value must be convertible to a boolean. When the value of this configuration parameter is false, any math operation that would require using bignums to calculate will instead be limited to the precision available in the **Tcl\_WideInt** type. The default value of this configuration parameter will be true \(i.e. use of bignums will be enabled by default, preserving backward compatibility\). # Reference Implementation Not yet complete; however, it will eventually be available on the **tip-392** branch of the Tcl source code repository. # Copyright This document has been placed in the public domain. |
Name change from tip/393.tip to tip/393.md.
|
| < | < | | | | | | | > | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 393: Add -command Option to lsearch Author: Pawel Salawa <[email protected]> State: Draft Type: Project Vote: Pending Created: 25-Apr-2011 Post-History: Tcl-Version: 8.7 ----- # Abstract This document describes new option for **lsearch** named **-command** that lets the developer define a custom comparision algorithm for searching for an element of a list. # Rationale The **-command** option would be very useful when someone wants to look for element on list, that contains objects \(TclOO, Itcl, etc\), or simply Tcl dicts. Specifying a command lets a developer to decide what data from objects in a list is important for the comparison. This is effectively introducing the **-command** option from **lsort** to **lsearch**. # Specification The option **-command** takes additional argument, which is a name of a command prefix that implements the comparison. The command prefix will have two extra arguments added during evaluation, being \(1\) the element of the list and \(2\) the pattern that is being sought. Thus, a suitable command might be defined like: proc searchCommand {listElement pattern} {...} And used like: lsearch -command searchCommand $list $pattern The command must return a boolean value, where true means that the element matches the pattern. Since the **-command** option specifies a comparision method, therefor it's treated the same way as **-exact**, **-glob**, **-regexp** and **-sorted** options are. It also causes some options \(e.g., **-integer**, **-nocase**\) to be ignored. # Reference Implementation <http://sqlitestudio.pl/tcl/patches/tip-393-lsearch-command.patch> Patch made against 8.6.0 beta. # Copyright This document has been placed in the public domain. |
Name change from tip/394.tip to tip/394.md.
|
| < | < | | | | | | | > | | | | | | | | | | > | 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 | # TIP 394: Platform-Independent Handling of Contemporary Mice Author: Andreas Leitgeb <[email protected]> Type: Project Tcl-Version: 8.7 State: Draft Vote: Pending Created: 30-Nov-2011 Post-History: ----- # Abstract This TIP proposes a change to Tk's Events such as to support new features of modern pointer devices \(mice\) in a platform-independent way. # Rationale Modern pointing devices \(mice\) do have more controls beyond the standard three buttons and one-dimensional scrolling gadget. They often have any of these as well: * Tilt-able scroll wheel * A second wheel for horizontal scrolling * A scroll-ball rather than a scroll wheel \(see Apple's "mightymouse"\) * Additional "forward" and "backward" buttons * even more buttons... On Linux platform, bind'ing on <Button> will catch all\(?\) or these \(and "%b" gives an ordinal number which allows for some heuristic recognition\). But even on Linux, it is not possible to bind specifically to e.g. <Button-8>, or to <B8-Motion> kind of events. On Windows platform, the system offers different types of events for certain different controls. An app would e.g. register extra to receive horizontal scroll events and those extra buttons. \(This is gathered from hearsay.\) # Proposal Just like the MouseWheel event that was added to Tk in response to wheel-mice filling the market, we'd have to define new events for each new control. For legacy-reasons, the dichotomy between vertical scroll wheel and buttons 4 and 5 will need to be preserved, maybe as well as the buttons 6 and 7 for horizontal scrolling. Any extra buttons could then be either named "X1", "X2", "X3", ... or numbered 8, 9, 10, ... which would reflect as bind events <Button-8> or <Button-X1>, but also <B8-Motion> or <BX1-Motion> For horizontal scrolling, <MouseWheelHoriz> would be the preferred way for cross-platform apps, but depending on whether "4 and 5" button events are already emulated for scrolling on windows, it would be worthwhile to also emulate "6 and 7" button events for horizontal wheel-activity. At this stage of this TIP the decision isn't yet made. # Copyright This document has been placed in the public domain. |
Name change from tip/395.tip to tip/395.md.
|
| < | < | | | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 395: New 'string is entier' Command Author: Jos Decoster <[email protected]> State: Final Type: Project Vote: Done Created: 13-Dec-2011 Post-History: Discussions-To: news:comp.lang.tcl Keywords: Tcl Tcl-Version: 8.6 Obsoletes: 347 ----- # Abstract The **string is** command supports tests for a number of Tcl's basic types, for example, integers, doubles, and booleans. One common case is missing: checking if a value is an integer number without particular storage width, unlike **string is integer** and **string is wideinteger**. This document proposes to augment the **string is** command with a **string is entier**. # Rationale Tcl makes it easy to work with integers larger than 64 bit \(big nums\). The **expr** command supports operations on unlimited bit widths. Checking if a string contains a valid integer value is possible with the **string is integer** and **string is wideinteger** commands for integers of particular storage widths \(e.g. 32 bit for integers and 64 bit for wide integers\). But checking if a string contains a valid integer wider than a **wideinteger** is not possible with a **string is** command. Checking if a string contains a valid big num can now be done with a regular expression or by **catch**-ing the **::tcl::mathfunc::entier** function. # Specification This document proposes to augment the **string is** command with a **string is entier** which functions the same as **string is integer** in every respect except for the fact that it accepts any string containing a substring that is valid as a bignum integer \(that is, acceptable to _Tcl\_GetBignumFromObj_\) possibly surrounded by whitespace. # Compatibility No incompatibilities are introduced. # Alternatives The **bignum** was rejected in favor of **entier** because **entier** is already used in **::tcl::mathfunc::entier**. # Reference Implementation A reference implementation is available here: <http://sites.google.com/site/josdecoster/Home/tip\_string\_is\_entier.diff> # Copyright This document has been placed in the public domain. |
Name change from tip/396.tip to tip/396.md.
|
| < | < | | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | < > | | | | | | | | | | | | | | | | < > | | | | < | > | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 396: Symmetric Coroutines, Multiple Args, and yieldto Author: Kevin Kenny <[email protected]> State: Final Type: Project Vote: Done Created: 11-Feb-2012 Post-History: Keywords: coroutine,yield,yieldto Obsoletes: 372 Tcl-Version: 8.6 ----- # Abstract A new command, **yieldto**, is proposed that allows a corouting to suspend its execution and tailcall into an arbitrary command. If the new command is another coroutine's resume command, we obtain symmetric coroutines. If the new command is the **return** command, we obtain the ability for a coroutine to present an unusual status \(e.g., _error_, _break_, _continue_ or _return_\) to its caller. The **yieldto** command also marshals the arguments as a list when the yielding coroutine is next invoked, allowing for the transmission of multiple arguments. # Rationale Several TIPS \(at least [[372]](372.md), [[373]](373.md), [[375]](375.md), and [[383]](383.md)\) have been advanced to propose various improvements to the coroutine control transfer provided by the **yield** command. This TIP attempts to distill the requirements of these TIPs into an irreducible minimum for implementation in 8.6 \(resolving a blocking issue for an 8.6 release\). This TIP intentionally leaves out of scope some of the more complex or controversial issues, such as enhancements to **info args** and **info default**, unusual return from a \`yield\` operation. and code injection into coroutines. It is believed that all of these can be added later, without introducing needless incompatibilities into the basic mechanisms of coroutine construction, invocation, and yielding. Requirements that are thought to be essential for this TIP include: **The ability for a coroutine invocation to implement any argument signature that an Tcl command can implement.** A coroutine invocation must be able to accept multiple arguments, and to allow for call-by-name \(or rather, call-by-quasi-value-result, see below\) parameter transmission. **The ability to return an unusual status.** A coroutine invocation must be able to return an error status or another unusual status \(e.g., _break_, _continue_ or _return_\) to its caller, and to perform a tailcall. **Support for symmetric coroutines.** Although it is well known that asymmetric coroutines \(such as Tcl 8.6 implements today\) and symmetric coroutines have equivalent power, the implementation of symmetric coroutines in a system that supports only asymmetric ones is possible only by coding a separate scheduler that allows an active coroutine to detach with a request to resume another. If symmetric coroutines are not implemented directly, it is likely that multiple incompatible schedulers will spring up in user code, greatly impeding a later unification. # Proposal The new command: > **yieldto** _cmd_ ?_arg1..._? shall accept one or more arguments: > _cmd_ - The name of a command to invoke in place of the current coroutine invocation. > _arg1..._ - The arguments to pass to the given command. It shall have the following effects: 1. The _cmd_ argument shall be resolved in the current coroutine's context, resulting in a command to invoke. If resolution fails, the error is presented in the coroutine's context. 2. The current coroutine shall suspend its execution in the same way as with the **yield** command. 3. The command that invokes the coroutine shall be placed into a state such that it will accept multiple arguments when it is next invoked, rather than the single argument demanded by **yield**. 4. The command and arguments shall be invoked in just the same way as if they had been called directly from the coroutine's caller. The given command replaces the coroutine invocation on the runtime stack. Data and status returned from the given command are returned to the context that invoked the coroutine. 5. When the coroutine is resumed, any arguments passed into the coroutine command are assembled into a list and returned as the value of the **yieldto** command. In other words, **yieldto** means "suspend the current coroutine and **tailcall** the given command: **yieldto** is to **yield** as **tailcall** is to **return**." In addition, **yieldto** causes the current coroutine to accept multiple arguments on its next invocation. # Relationship with the Earlier Proposals [[372]](372.md) proposes a **yieldm** command that allows a coroutine to yield and subsequently accept multiple arguments when resumed. The requested functionality of [[372]](372.md) can be layered trivially atop this proposal: a one-line implementation of the **yieldm** command would be: > interp alias \{\} yieldm \{\} yieldto return -level 0 [[373]](373.md) proposed **yieldto** together with a separate **yieldset** command. The latter allowed a coroutine to designate a set of arguments and defaults. The advantage over simply passing the arguments as a list was that error messages for incorrect numbers of arguments could be generated automatically, and that **info args** and **info body** could introspect into the desired argument list. Since the error message generation can be done readily by auxiliary procedures, and the introspection is something of a nicety, this proposal defers the implementation of **yieldset**. [[375]](375.md), which replaced [[373]](373.md), proposed a **yieldto** command that is the same as the current proposal's, except that it could transmit only a single argument when the coroutine was resumed. As such, it was incomplete as it stands. [[387]](387.md) proposed a unified syntax for all of the above TIPs. The proposed syntax was quite complex, and its only advantage over the current proposal is that is allowed for introspection using **info args** and **info body** and for automatic generation of error messages for incorrect arguments. Since these are regarded as something of a nicety, the author of the current proposal believes that their consideration can be deferred in favour of the current proposal. The related [[383]](383.md) addresses a different set of issues: injecting code into a suspended coroutine for the purpose of debugging. Its implementation can be decided on independently of this TIP. # Examples: ## 1. Multiple arguments and error returns. Let us assume that there is a coroutine **foo** that wishes to accept at each invocation two arguments **bar** and **grill**. It therefore needs to accept multiple arguments, and to check the number of arguments, returning an error to its caller if they are incorrect. Code structured like the following can serve both purposes: # presume that $value is the value to return to the last invocation for {set args [yieldto return -level 0 $value]} \ {[llength $args] != 2} \ {set args [yieldto return -level 0 -code error \ -errorCode {MYCORO WRONGNUMARGS} \ "wrong # args, should be \"foo bar grill\""]} { # do nothing } lassign $args bar grill ## 2. Symmetric coroutines. It may not be obvious from the foregoing discussion that the original purpose of **yieldto** was imagined to be passing of control between peer coroutines. For instance, if we assume that there are two coroutines, **producer** and **consumer**, and that calling **producer** returns a string while calling **consumer** accepts a string and returns nothing, then each coroutine may yield to the other: _Code in_ **producer**: yieldto consumer $string _Code in_ **consumer**: lassign [yieldto producer] string ## 3. Call by name. It turns out that **yieldto** allows for a rough simulation of Tcl's call by name, although it requires explicit transmission of values between coroutines, rather than a simple **uplevel** operation. Let us assume that a caller invokes a coroutine with the name of an array, and that the coroutine wishes to set elements of that array. A procedure like the following will give approximately the desired result. proc remote-set {varName value} { lassign [yieldto remote-set-worker $varName $value [info coroutine]] \ status result return -code $status $result } proc remote-set-worker {varName value coro} { tailcall $coro \ [catch {uplevel 1 [list set $varName $value]} result] \ $result } \(Proper transmission of the options dictionary from **catch** is omitted for the sake of simplicity.\) Let's look at what happens when code in the coroutine _mycoro_ does remote-set array(key) value 1. The **remote-set** procedure yields to the command remote-set-worker array(key) value mycoro 2. The **remote-set-worker**, executing in the calling coroutine, invokes set array(key) value > in its caller's scope, capturing the status and return value. Presuming that the variable was set successfully, It then invokes mycoro 0 value > as a tailcall, re-entering the _mycoro_ coroutine. The two-element > list, \{0 value\}, becomes the return value of **yieldto** 3. The **remote-set** procedure returns the same status and result that the **set** command returned. This technique actually shows how arbitrary commands may be executed in a calling coroutine. The way this is done opens some interesting possibilities for tools such as debugging interactors. For instance, a **trace** callback might invoke a debugging coroutine to interact with the user, allow the user to execute arbitrary commands to probe the state of the code being debugged, and then transparently resume at the place that the code left off, without otherwise disturbing its stack. # Implementation notes The **yieldto return** idiom is expected to be used widely, since it is the way to present unusual status codes, and internally is used in the implementation of **yieldm**. For this reason, the implementation may contain code to optimize it specially. # Acknowledgments The implementation of this TIP, and most of the details of its specification, are actually the brainchild of Miguel Sofer, who expresses a continued interest in seeing it implemented while being unwilling at the present time to shepherd it through the sometimes acrimonious discussions on tcl-core. To him belongs all the credit for the ideas: any errors in the specification as presented here are the author's. Thanks are due to Donal Fellows, Joe English, Andreas Leitgeb, and Lars Hellström for making needed corrections to the initial version of this TIP. # Copyright This document has been placed in the public domain. |
Name change from tip/397.tip to tip/397.md.
|
| < | | | | | | < | | | > | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 397: Extensible Object Copying State: Final Type: Project Tcl-Version: 8.6 Vote: Done Post-History: Author: Donal K. Fellows <[email protected]> Created: 13-Feb-2012 Keywords: Tcl, TclOO, copy, clone ----- # Abstract This TIP proposes a mechanism whereby an object or class can provide additional control over how it gets copied to a new one by the **oo::copy** command. # Rationale I always knew that TclOO's **oo::copy** command was not particularly complete, in that only the C-level state was copied. The vast majority of state associated with an object \(notably including its variables\) was not copied on the grounds that the caller of **oo::copy** could do that for themselves. However, this has not proved particularly workable in practice once someone actually started to use the mechanism. It turns out that the callers of **oo::copy** expect a full copy of the object to be created. This is quite challenging because some things associated with an object are tricky to copy correctly. For example, if an object has a number of Tk widgets under its control, or has timer callbacks set up, these are very challenging for a generic object copying scheme to detect \(and generic copying of Tcl commands is difficult anyway\). Fortunately, we already have a mechanism for handling such per-object variation: methods. # Proposed Change I propose that the **oo::copy** command will internally call the newly created object's **<cloned>** method \(passing in the name of the source object as the only argument\) to allow for the customization of the copy. If the method fails \(throws an exception\), the copy will be destroyed and the error propagated. > _copiedObject_ **<cloned>** _sourceObject_ Furthermore, a default implementation of the **<cloned>** method will be created in **oo::object** which will duplicate the variables and procedures \(note, not other commands\) of the source to the copy. This method will not be exported by default \(nor should it be; the method is not intended to be called directly\). # Reference Implementation See the "development-rfe3485060" branch of the tcloo repository: <https://core.tcl.tk/tcloo/timeline?r=development-rfe3485060> # Copyright This document has been placed in the public domain. |
Name change from tip/398.tip to tip/398.md.
|
| < | < | | | | | | | | > | | | | | | | | < | > | | | | | | | > | 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 | # TIP 398: Quickly Exit with Non-Blocking Blocked Channels Author: Alexandre Ferrieux <[email protected]> State: Final Type: Project Vote: Done Created: 24-Feb-2012 Post-History: Keywords: close,exit,flush,blocking,nonblocking Tcl-Version: 8.6 ----- # Abstract This TIP reverts an age-old documented behavior that is useless, and the ill effects of which cannot be circumvented: Tcl's insistence on flushing even non-blocking channels on exit. # Rationale The close.n manpage says: > Channels are automatically closed when an interpreter is destroyed and when the process exits. Channels are switched to blocking mode, to ensure that all output is correctly flushed before the process exits. So, assuming the application has been using nonblocking IO all the time to stay responsive even with blocked sockets \(network failures\) or pipes \(stalled consumer\), if it decides to give up and exit, it _cannot_ do so today: Tcl will switch those channels back to blocking mode, and sit forever trying to flush them, until a kind hand hits ^C. No combination of **close**/**fconfigure**/**exit** will do, thanks to the above clarification. Note that the intent of this behavior is to automagically prevent careless applications from truncating their output. The flaw of this logic is that such careless applications typically don't use nonblocking channels. Hence the generalization is abusive. Hence, the proposal of this TIP is simply to revert this deleterious choice. This way: * simple apps continue to autoflush their blocking channels, * smart nonblocking contraptions enjoy a timely exit, and * generic code can even guarantee quick death by switching all channels to nonblocking mode, like this: proc instantdeath {{status 0}} { foreach ch [chan names] {fconfigure $ch -blocking 0} exit $status } # Specification Nonblocking channels shall no longer be switched to blocking mode when the process calls **exit** or _Tcl\_Exit\(\)_. Any buffered data for nonblocking channels will be discarded. # Notes Blocking channels are unaffected by this TIP; blocking channels shall still be flushed and closed at **exit**-time # Related Bugs Bug 2946474 noted the accidental, non-TIP-warranted suppression of this strange behavior. Fixing this bug simply meant to comply with Day One documentation. This TIP now judges the substance. # Reference Implementation Branch tip-398-impl holds the code. # Copyright This document has been placed in the public domain. |
Name change from tip/399.tip to tip/399.md.
|
| < | < | | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 399: Dynamic Locale Changing for msgcat Author: Harald Oehlmann <[email protected]> State: Accepted Type: Project Vote: Done Created: 27-Mar-2012 Post-History: Keywords: Tcl,localization,msgcat Tcl-Version: 8.6 Obsoleted-By: 412 ----- # Abstract This TIP adds dynamic locale switching capabilities to the **msgcat** package. # Rationale Within a multi-language application like a web-server, one may change the locale quite frequently, for example if users with different locales are requesting pages. Unfortunately, this does not fit well with the model adopted by the **msgcat** package, which assumes that all code follows this sequence: 1. Set locale list: **mclocale** _locale_ 2. Load language files with other package load: **mcload** _msg-folder_ 3. Translate strings: **mc** _key args..._ Note that if the locale should be changed after other packages are loaded, one must restart at step 2. This requires reloading all packages which is mostly not practical. The key issue is that **mcload** only loads language files included in the current locale \(**mcpreferences**\) and does not load any others. The aim of this TIP is to extend **mcload** to load additional language files. Then **mclocale** may be called to change the locale on runtime without the need to re-execute **mcload** \(which would normally imply to reinitialise or reload the package\). # Specification This TIP proposes to add a new command: > **msgcat::mcconfig -pattern** ?_patternlist_? This command may get or set package options. There is currently one option "**-pattern**". Options may be set using > **msgcat::mcconfig** _option value_ ?_option_? ?_value_? Current option values may be read using: > **msgcat::mcconfig** _option_ ## Option -pattern The option **-pattern** consists of a list of language file name patterns like **fr\***, **\***, or **fr\_ch**. Any **mcload** command executed after this setting will consider this list _in addition_ to the current locale list. Files are searched using a **glob** command per element on the specified pattern plus the string ".msg". If "fr\*" is specified within the pattern list, the file search pattern is "fr\*.msg". The default option value is the empty list \{\}. In consequence, only files covered by the current locale list are sourced. # Example Usage Imagine an application which supports the current user language and French, German and English. An external package **tp** is used. The package uses **msgcat** and performes within the **package require tp** call: package require msgcat msgcat::mcload [file join [file dirname [info script]] msgs] An implementation of the application with the current msgcat 1.4.4 would require the following initialisation sequence: package require msgcat package require np and the following code to change the locale to French: package forget np msgcat::mclocale fr package require np Using the extension of this tip, the required code for initialisation is: package require msgcat msgcat::mcconfig -pattern {fr* de* en*} package require np and to change to french locale: msgcat::mclocale fr Within this modification, locale change is a cheap operation. Before, it was computational expensive \(if possible, as many packages are not reloadable or a reload may disturb current processing, e.g., by forcing the closing of sockets, etc.\). # Reference Implementation See Tcl Feature Request 3511941. <http://sourceforge.net/support/tracker.php/?aid=3511941> # Compatibility No incompatibilities are introduced. # Issues Packages might not be aware of a locale change and may buffer translations outside of **msgcat**. Packages should not buffer msgcat messages if they are used in a dynamic locale application \(like tklib tooltip does for example\). # Alternatives This implementation requires the setting of the pattern before any package with msgcat is loaded. To avoid this, msgcat must store all paths passed by any **mcload** call. When a locale change happens, any currently missing files are loaded. This requires much more housekeeping and may lead to side effects, especially if packages are not aware of the fact that their package files are loaded outside of the **mcload** command. # Copyright This document has been placed in the public domain. |
Name change from tip/4.tip to tip/4.md.
|
| < | < | | | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 4: Tcl Release and Distribution Philosophy Author: Brent Welch <[email protected]> Author: Donal K. Fellows <[email protected]> Author: Larry W. Virden <[email protected]> Author: Larry W. Virden <[email protected]> State: Draft Type: Informative Vote: Pending Created: 26-Oct-2000 Post-History: Discussions-To: news:comp.lang.tcl ----- # Abstract This document outlines how Tcl should be distributed, with particular reference to issues related to building a distribution with the _batteries included_ so that most people can have access to the useful extensions without having to chasing halfway across the 'net for them. # Overview Tcl has traditionally been a "core" that is extensible with binary extensions and Tcl scripts. There have been two styles of Tcl distributions: source and binary. The Tcl source distribution contains the Tcl "core" and a small number of support scripts. The binary distributions have included Tk, and in some cases \(e.g., TclPro\) other extensions like [incr Tcl], TclX, and Expect. Users with access to a compiler can get source distributions of the various extensions and compile them for their own installation. _\(Thanks to Bob Technetin <[email protected]> for the inspiration for these pictures - DKF.\)_ ![Traditional Tcl Distribution Architecture](../assets/4layers1.gif) This proposal formalizes the notion of a small Tcl source core and larger distribution bundle that includes one or many extensions. The distribution can be in source or binary form. The goal is to keep a small core that is suitable for embedding with the smallest footprint, while acknowleding that desktop users and application developers want a larger _standard distribution_ that has a set of well known and widely used extensions. The goal of this proposal is to establish a standard for future Tcl distributions. There will be two kinds of Tcl distributions: a small core suitable for specialized embedded applications, and a larger bundled distribution suitable for more general application development. ![Batteries-Included Tcl Distribution Architecture](../assets/4layers2.gif) # The Tcl Core Distribution The Tcl "core" should remain as small as possible, and could become smaller in the future as certain features are moved into extensions. The "core" distribution must include: 1. The C sources required to create the Tcl binary library. 1. The C sources required to create a "Tcl Shell" application. This is commonly known as "tclsh". 1. The Tcl script libraries that implement the code library and packaging systems. This includes the "unknown" command and various commands related to auto loading of packages. 1. The Tcl test framework used for testing the Tcl binary library and the support scripts. Additional items may appear in the "core" distribution, especially for historical reasons. But, some Tcl scripts and binary extensions that currently exist \(as of Tcl 8.3\) in the Tcl source distributions may migrate into the larger distribution described below. # The Bundled Distribution The _bundled_ Tcl distribution will contain Tcl, various binary extensions, and various Tcl script packages. This proposal establishes an initial set of binary extensions, but following the model and using the distribution infrastructure we create, various bundles should be easily created. Each package included in the bundled distribution must have a test suite and documentation. At this stage the documentation will probably be in a variety of formats, but ultimately we should standardize on an XML-based representation and supply tools that generate other formats from that representation. # Mandatory Packages The bundled distribution must include \(but is not limited to\): 1. The "core" distribution described above. 1. The Tk toolkit for GUI applications. This includes the well known "wish" shell application. 1. The registry and dde extensions for the Windows platform. 1. The [incr Tcl] extension. 1. The TclX extension. There are some historical features of TclX that should not necessarily be included, including the tclx shell and its alternate library format. However, the TclX help system should not only be included, but updated to include info on all commands included in the distribution. 1. The Expect extension for UNIX platforms. 1. The TkCon enhanced console application. # Optional Packages In addition, it is likely that several of the following packages will be included in the bundled distribution, as well as others not listed. 1. The Standard Tcl Library of Tcl scripts. Currently this includes packages for: > 1. base64 encoding/decoding > 1. file utilities > 1. command line processing > 1. FTP client library > 1. FTP server > 1. HTML and JavaScript generation > 1. Math and statistics utilities > 1. MIME encoder and parser > 1. CGI processing \(ncgi\) > 1. NNTP client > 1. POP3 client > 1. Profiler for Tcl scripts > 1. Event counters and interval timers > 1. Structures, including tree, stack, graph, queue > 1. URI parsing > 1. Text string manipulation utilities \(trim, tab, etc.\) 1. BLT. 1. [incr Tk] and [incr Widgets]. 1. TkTable. 1. The Standard Tk Library of Tcl/Tk scripts. Currently this includes packages for: > 1. BWidgets > 1. mclistbox 1. Img # Rationale The small "core" distribution must retain its identity for those applications that embed the Tcl interpreter into constrained environments and require a small footprint. The footprint must remain small, and in fact it should grow smaller, if possible. For example, in the early days of Tcl it was possible at compile time to remove all the file system and exec commands to create a very small Tcl core. There are wide variety of vendors that embed Tcl into, e.g., CAD applications, router firmware, and other limited environments. They only need the basic commands for procedural programming and basic data types. The larger, bundled distribution must become the standard for desktop distributions \(e.g., Linux\) so that application writers have a richer set of Tcl commands that they can assume are available. This includes the [incr Tcl] class system and the OS-specific commands provided the TclX and the registry and dde extensions. The set of packages in the bundled distribution are divided into _mandatory_ and _optional_ packages. The intent of this distinction is to set a goal for the initial _bundled_ distribution, but not close the door to inclusion of other packages. Over time the set of packages in the bundled distribution will surely grow, and some packages may become superceeded by other better packages. The _mandatory set_ of packages, however, should be common among all bundles to application writers know what to expect. In particular, the mandatory set includes [incr Tcl] to promote object oriented programming, Tk to promote easy GUI development, TclX, Dde and Registry to provide access to OS-dependent functionality, and Expect to support automated test environments. At this time there are a variety of Tk widgets that are optional because there is some overlap and we anticipate continuted evolution of the Tk widget set. I expect that the first bundle will include all the major widget sets, including BLT, [incr Tk] and [incr Widgets], TkTable, the "vu" collection, and possibly Tix. # The Role of the TCT The larger bundled distribution will contain packages that are "owned" by the TCT and some that are not. The whole process will be more scalable if responsibility for packages can be split out to other individuals and groups. The role of the TCT should be to set up the infrastructure for the bundled distribution and to make _official_ bundled distributions. # Issues The main purpose of this proposal is to establish three things: 1. The continued existence of a small Tcl "core" that is identifiable unto its own and useful to various specialized embedded applications. 1. The creation of infrastructure to create bundled distributions. The exact nature of this bundling is not specified. The first bundles may well be created by hand crafted Makefiles and distribution-creation scripts. 1. The set of _mandatory_ extensions that should be included in any Tcl bundle. The list in the first draft of this TIP is likely to be wrong, and will surely be amended in the future. 1. Whether further distinctions should be introduced to better support people who wish to target Tcl towards small devices or embedded environments better. ![Refined Tcl Distribution Architecture](../assets/4layers3.gif) There are a number of related topics that are deliberately outside the scope of this TIP: 1. Documentation format. 1. Network aware downloading of packages and more sophisticated package management. 1. Details of the compile and build environment. Currently there is the TEA standard, and the packages listed in the Mandatory set have all been set up for TEA as part of TclPro. # Copyright This document has been placed in the public domain. |
Name change from tip/40.tip to tip/40.md.
|
| < | < | | | | | | | | | > | | | | | | | | | | | | | | < > | | | < > | | | | | < > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 276 277 278 279 280 281 282 283 284 285 286 | # TIP 40: Documentation Generator for Tcl Scripts Author: Arjen Markus <[email protected]> Author: Donal K. Fellows <[email protected]> State: Withdrawn Type: Project Vote: Pending Created: 04-Jul-2001 Post-History: Keywords: documentation,automatic generation,HTML,reference Tcl-Version: 8.0 ----- # Abstract This TIP proposes the adoption of a standard documentation format for Tcl scripts and the implementation of a simple tool that will extract this documentation from the source code so that it may be turned into a programmer's guide. This is in essence akin to documentation tools like the well-known _javadoc_ utility for Java programs and Eiffel's short utility. # Introduction The style guide by Ray Johnson presents a documentation standard that is easy to use and is in fact adopted in the Tcl/Tk distribution. Other than this, the standard has not been enforced or encouraged. It is also not backed up by some tool \(as far as I know\) that can generate pretty looking documents from this. As a consequence, styles of documentation may vary widely and at times it is necessary to read the source code \(looking for descriptions\) to understand how to use the script. The availability of such a tool may encourage people to use the standard, as the costs of generating the documentation are relatively low. The tool must accommodate for variations and therefore be flexible - for instance by providing customisable procedures to support the user's preferred header format. The tool also needs to distinguish the types of output: in many cases HTML output is desirable to make it look pretty and provide hypertext facilities, in other cases it should provide plain text, formatted so that it can be read in any ordinary text editor or printed quickly. Parallel to the development of such a tool, a standard or checklist should be assembled of what information programmer ought to provide, the version of Tcl/Tk, extensions that need to be present, what functionality is offered and so on. # Rationale Automatic documentation generation has two goals: improving usability and improving maintainability. The first means: pleasant looking documentation, at low cost for the author, is easy to use. One can also avoid reading the source code. Further, it ensures homegeneously looking documentation. Improving the maintainability is achieved by having more or less technical documentation near the code. There is no need for separate documents, something which enhances the risk of discrepancies. Remember the DRY principle: Don't Repeat Yourself. # What information A user clearly needs different information than a maintainer. For the user it is important to know what functionality is provided, what other packages or extensions are needed, which \(public\) procedures are available and how to use them. For the maintainer: having an overview of the source files helps finding the procedures. Part of this information can be extracted directly from the source \(such as via inspection of the proc, package and namespace statements\). # Formats Use the format proposed by the style guide as a guideline \(certainly for the reference implementation\): # pkg_compareExtension -- # # Used internally by pkg_mkIndex to compare the extension of a file to # a given extension. On Windows, it uses a case-insensitive comparison # because the file system can be file insensitive. # # Arguments: # fileName name of a file whose extension is compared # ext (optional) The extension to compare against; you must # provide the starting dot. # Defaults to [info sharedlibextension] # # Results: # Returns 1 if the extension matches, 0 otherwise \(This comes from the "package.tcl" script file that came with Tcl 8.3.1, it is consistent with the Tcl style guide by Ray Johnson\) # Requirements The requirements are simple to describe: * Implementation shall be in Tcl, to guarantee availability and portability. * The system shall be easy to extend to new documentation formats \(Implementation note: small procedures that register the information piece by piece\) * It shall be easy to extend to new output formats \(Implementation note: small procedures that format the registered information\) * It shall properly deal with organisational aspects: source file, package, namespace. # Summary of reactions The replies on the first version of this TIP were quite positive: both Donal Porter and Cameron Laird think it is a good idea. Juan Gil gave a very extensive reaction, describing a more general framework that would eventually result in a system for generating all kinds of output from Tcl scripts, TIPs and so on. To do him more justice, without repeating the entire document, he proposes the use of XML as an intermediate format holding the structure of the information. The advantage is the possibility to reuse all existing tools and \(de facto\) standards, notably DocBook, in this context. Even though I share some of the enthousiasm of Juan, I am a bit awed by it: the original idea of this TIP is not so much creating a publication system, but rather an easy-to-use tool for automatically extracting useful information in a nice shape. Eventually it could develop into something of the kind Juan describes, but that should not be the first goal. The technique for representing the information structure he proposes, is quite useable \(and akin to the rendering process of TIPs\): * Parse the script and store the pieces in "qualified lists". * Such qualified lists are an intermediate format, either in memory or stored in a suitable format on disk. * These lists and lists of lists are then passed to the output renderers. The first problem to solve is then finding a suitable structure for the information we need to extract. This is the subject of the next section. Will Duquette and Andreas Kupries mentioned the frequent use of specialised commands that introduce new commands \(rather than a straightforward call to "proc"\). This feature will have to be looked into, because if you only look for lines like "proc some-command \{ ... \} \{", you might well miss the essentials of such applications. # Information in a Tcl script Tcl scripts are organised in three essentially unrelated ways: * Individual files contain the code * Programs consist of one or several files of code * Packages are used to identify code that belongs together In practice these methods will be used in accord with each other, but there is no guarantee for instance, that a source file contains only one package and programs will probably quite often use more than one package. On a smaller scale, the following items are of importance: * Procedures or commands defined inside some namespace \(exported or not\) * Variables local to the enclosing namespace or global to the application For a user it will be important to know what a program or package has to offer and how to get this functionality: * A description of the program \(with its command-line arguments, if any, the packages it uses, if they come separately\) * A description of the package or packages \(assuming it is properly installed, its name and version should be enough to load the scripts and binaries\) * A description of each public procedure and a description of the arguments and the result, if any * A list of all other requirements \(other packages or the Tcl version?\) For a maintainer of the code, additional information would include: * A list of all variables \(local to the namespace and global\) that are used in the various procedures * The contents of each source file \(so where does each procedure live?\) * Detailed maintenance issues that have been written down in comments in the code A possible structure in which all this information can be stored and retrieved is sketched below: program: version source files (list of) packages (list of) procedures (list of) command-line arguments: description of each option and the values (if any) associated with it description of other arguments (such as file names) source files: packages (list of) procedures (list of) packages: package A: description version requirements Tcl-version packages that are required local and global variables: variable D: used by which procedures? variable E: used by which procedures? ... procedures: procedure F: description exported or not arguments: argument G: description argument H: description ... result: description procedure I: ... Except for the descriptions, all these items can - at least in principle be extracted automatically. So, even though the programmer has been too lazy to describe his/her procedures in detail, some information can be retrieved about the use of global data for instance and the complexity of the argument lists. Note that as far as the three methods of organisation is concerned, there is no attempt to define a practical relationship between them. To refer to the example above: procedure: pkg_compareExtension description: "Used internally by pkg_mkIndex to compare the extension of a file to a given extension. On Windows, it uses a case-insensitive comparison because the file system can be file insensitive." arguments: argument fileName: description: "name of a file whose extension is compared" argument ext: description: "(optional) The extension to compare against; you must provide the starting dot. Defaults to [info sharedlibextension]" result: description: "Returns 1 if the extension matches, 0 otherwise" By adopting a tree structure to represent the information extracted from the source code, one can be as flexible as probably needed. For instance, suppose one would like to extract certain metrics, like the number of lines or the cyclometric complexity. This could then be an additional node in the subtree for the command procedure, besides the list of arguments, the result and the description. # Copyright This document is placed in the public domain. |
Name change from tip/400.tip to tip/400.md.
|
| < | | | | | | < | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 400: Setting the Compression Dictionary and Other 'zlib' Updates State: Final Type: Project Tcl-Version: 8.6 Vote: Done Post-History: Author: Donal K. Fellows <[email protected]> Created: 30-Mar-2012 Keywords: Tcl, zlib ----- # Abstract Sometimes it is necessary to set the compression dictionary so that a sequence of bytes may be compressed more efficiently \(and decompressed as well\). This TIP exposes that functionality. It also reduces the number of inconsistencies in the **zlib** command. # Rationale The SPDY protocol extensions to HTTP require the seeding of the zlib compression dictionary \(which greatly improves the performance of compression on small amounts of data, such as HTTP headers\). In order to allow a pure Tcl implementation of the SPDY protocol, it is therefore necessary to provide a mechanism whereby the compression dictionary \(a byte-array, normally up to 262 bytes long according to the zlib documentation\). There is to be no mechanism for retrieving the compression dictionary generated by the compression engine; there is no API for doing that. A side issue discovered during working on this TIP was that there was considerable variation in what could be achieved by various parts of the API. In partcular, it was identified that the API was inconsistent, providing access to some features in "simplified" parts of the API that could not be controlled from the "advanced" parts \(e.g., there was no way to set the GZIP header descriptor with **zlib stream gzip**\). # Proposed Changes: Tcl ## Changes to the Channel Transforms The **zlib push** command will gain two extra options, **-dictionary** and **-limit**: > **-dictionary** _bytes_ This option will provide a compression dictionary to be used \(_bytes_ is a byte-array used to initialize the compression engine\) which will be supplied to the zlib compression engine at the correct moment during compression or provided on request of the compression engine on decompression. The _bytes_ argument must be non-empty if given \(we will not enforce a limit on the length of the dictionary, but using an excessively long one may cause the zlib engine to issue errors\). This will be illegal to use with **gzip** and **gunzip** streams, and its use with raw \(**deflate**\) streams will be not recommended due to the difficulty of detecting whether a compression dictionary was applied; the zlib-format header adds very little overhead. This value can also be set with **chan configure**, though doing so after data has started to be pushed through the compression engine \(except if an error requesting a compression dictionary was received\) is not recommended. > **-limit** _size_ This option \(valid on the three decompressing transforms only, and where _size_ must be a positive integer of no more than 0x10000\) allows for control over the size of chunks read from the underlying channel for feeding into the decompression engine. Its default is 1, which makes for the correct behavior under the widest range of conditions, but at a significant cost in terms of computational complexity: when the underlying data source is known to never block for long and to have complete data, a larger value can be used which will greatly improve performance. This value can be set at runtime using **chan configure**. ## Changes to the Streams The **zlib stream** command will also gain some complexity. In particular, the **compress**, **decompress**, **deflate** and **inflate** subcommands will gain the ability to take an extra **-dictionary** _bytes_ pair of options \(same interpretation as above\), as will the **add** and **put** subcommands of the stream instance command. In addition \(as a correction to the functionality originally proposed in [[234]](234.md)\) the **zlib stream gzip** subcommand will also gain the ability to take: > **-header** _dict_ \(where _dict_ is a Tcl dictionary such as is passed to the **-header** option to **zlib gzip** and not a compression dictionary\), and the stream instance subcommand will gain a **header** subcommand to retrieve the gzip header \(it will be an error to use it on a stream not produced by **zlib stream gunzip**\). In order to facilitate the above change, the compression level used in that case will be altered to be specified via an option: > **-level** _compressionLevel_ # Proposed Change: C At the C level, one additional function will be provided: > void **Tcl\_ZlibStreamSetCompressionDictionary**\(Tcl\_ZlibStream _zshandle_, Tcl\_Obj \*_compressionDictionaryObj_\) This sets the compression dictionary for a particular stream to the given \(byte-array\) Tcl\_Obj, which will be duplicated. It is the caller's responsibility to dispose of the object passed in if they allocated it; they may do so immediately after calling this function. # Copyright This document has been placed in the public domain. |
Name change from tip/401.tip to tip/401.md.
|
| < | < | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | < > | | < > | | < > | | | | | | < > | < | > | | | | | | | | | | | | | | < | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | < < > > | | | | | | | | | | | | | | | | | | | | | | | | | | < > | | | < < | > > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | < < > > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 | # TIP 401: Comment Words with Leading {#} Author: Lars Hellström <[email protected]> State: Draft Type: Project Vote: Pending Created: 29-Apr-2012 Post-History: Tcl-Version: 8.7 ----- # Abstract The basic syntax rules of Tcl \(the "dodekalogue"\) are modified to allow words that are comments. In analogy with the argument expansion **\{\*\}**, such comment words will begin with **\{\#\}** \(left brace, hash sign, right brace\). The change concerns both words in scripts and, more importantly, words in lists. # Rationale Tcl is special in that comments appear at the "statement" \(command\) level of the language syntax rather than the "token" level \(as is the case in e.g. the ALGOL language family: C, Pascal, Java, etc.\). This means a Tcl program has fewer places in which a comment can be placed than many other languages, but this has not been a serious problem in traditional Tcl programming as commands tend to be short \(except when they have arguments that are themselves Tcl scripts\) and places where a comment can be inserted thus frequent enough. Recent developments in the language have however changed this. Various new features -- particularly dictionaries, ensembles, and argument expansion \(all of which were introduced with Tcl 8.5\) -- have encouraged a coding style where occasionally fairly large blocks of code can be spent setting up data structures as explicit values. For example, an ensemble that relies on the **-map** option typically has the entire mapping dictionary as a braced word in the code, and this can grow rather large if subcommands are being mapped to command prefixes of length greater than one. **string map** mappings can grow very large if there are many cases to deal with. Dictionaries have greatly simplified the use of values with inner structure, and as a result the complexity of the data that routinely gets passed to package commands has increased; a controlling data structure \(e.g. a grammar, in the case of a parser\) that once required an entire API of constructors to build might now have been redesigned as a simple nested dictionary that can be written raw in the code. And on top of it all, the various examples given above are not excluding each other, but may rather nest to form even larger blocks of code without any part that is a script. Adding a class of comments that can begin anywhere a word can begin undoes the forced "comment desert" status of such code blocks, because words are syntactic units not just in commands but also in lists, and all of the structured explicit values mentioned above are syntactically either plain lists or lists with additional restrictions. A parallel development is that the gap between what some piece of Tcl looks like at coding time and at runtime has begun to widen, because an increasing number of APIs call for fragments of commands \(particularly command prefixes\) rather than full commands or scripts. This change is often good from a correctness and efficiency point of view, but can make code harder to maintain on account of being more obscure; the evocation of runtime calls resulting from a particular piece of code sometimes requires a considerable effort of imagination, even if all APIs involved are well documented. Comment words that appear in the position\(s\) where additional material is inserted at runtime can help the mind here, by letting the eyes see in the code those things that will be there when it is evaluated, e.g. rather than socket -server [list ::some::handler $settings] $port one might write socket -server [ list ::some::handler $settings {#}chan {#}client {#}clientport ] $port to emphasize the fact that this **::some::handler** command takes those four things as arguments, even though only one of them is present in the command prefix. For command words to not change the interpretation of any presently legal syntactic construction, they must be something which is not valid as a list element word. The brace-something-brace-something syntax region where argument expansion was given a home is pretty much the only possibility there is for this \(if one rules out unbalanced words\), since there is very little that the Tcl parser finds outright wrong. The **\#** character is the normal way of starting a command-level comment, so it is natural that it occurs also in the syntax of word-level comments. # Specification Clause 5 \(argument expansion\) of the Tcl.n manpage is to be amended with the following conditions, and the language parser is to be modified accordingly. > If a word starts with the string "\{\#\}" followed by a non-whitespace character, then the leading "\{\#\}" is removed and the rest of the word is parsed and substituted as any other word. The result of this substitution is not used for anything, and no word is added to the command being substituted. For instance, "cmd a \{\#\}\{b c\} d \{\#\}e f" is equivalent to "cmd a d f". Moreover, the analogous modification shall be made to the list parser; a word with **\{\#\}** proper prefix is recognised as a comment also in a list, where the initial substitution phase only performs backslash substitution. _Note 1:_ The point of doing substitution is to stick as close to the behaviour of **\{\*\}** as possible. Of the three steps involved in argument expansion - parse and substitute word, reparse result without substitution as a list of words, and append those words to command being built -- only the middle one need to be different for **\{\#\}**, and thus a lot of the code can be shared. _Note 2:_ The comment prefix is typically most useful with words like cmd {#}{some [text]} {#}bareword {#}"Comment goes here" but things like this are also legal: cmd {#}$var {#}$x,\n {#}[foo bar] _Note 3:_ It is _very_ important for serveral use-cases that comment words are recognised as such also in lists. One might \(as I would\) argue that this should really follow automatically, since outside the source itself the only \(and not very explicit\) documentation of the string representation of lists is found in the lindex.n manpage which merely says that: > In extracting the element, **lindex** observes the same rules concerning braces and quotes and backslashes as the Tcl command interpreter; however, variable substitution and command substitution do not occur. As only variable and command substitution are mentioned as things which differ between lists and commands, they therefore must treat **\{\#\}** the same. However, presently the argument expansion **\{\*\}** is not recognised in lists, despite there not being a stated exception for that either. \(This state of affairs is reasonable, since it would be very complicated to extend present mechanisms to support argument expansion in lists and the benefit of doing so is slim at best, but it should be more clearly documented.\) # Use Cases ## More comments in switch Beginning with an old issue, one may consider the placement of comments to **switch** cases. The current advice is to place them first in the bodies \(which of course works\), but it can often be exposition-wise more natural to place them before the pattern, especially if there is not a 1-1 correspondence between comments and bodies. switch -regexp [string trimleft $number +-] { {#}"Integer formats" {^0$} - {^[1-9][0-9]*$} { # ... } {^0o[0-7]+$} { # ... } {^0x[0-9A-Fa-f]+$} { # ... } {#}"Float formats" {^[0-9]*\.[0-9]+(e[+-][0-9]+)$} - {^[0-9]+\.[0-9]*(e[+-][0-9]+)$} - {^[0-9]+e[+-][0-9]+$} { # ... } } ## Inline comments in long commands Some commands can be very long simply because they require a lot of arguments to express what one wants, and then comments can help clarify what a particular argument contributes to. $canvas create polygon 0 0 {#}"left top" 30 0 {#}"bend down" 30 30 \ {#}"concave part" 60 30 {#}"bend up" 60 0 {#}"right top" 90 0 \ {#}"curving back" 90 30 45 67 0 30 {#}"done" -smooth true \ -width 2 -fill orange -outline green {#}"Official colours" \ -tags {button {#}"for clicking" buoyant {#}"affects movement"} If there are several ideas in such a command, it might be nice to put the comments pertaining to each next to where that idea actually shows up in the code. ## Inline argument descriptions The Tcl style guide for C code suggests that comments describing function arguments appear inline with the argument declarations. Comment words would permit the same style in Tcl code. proc tcl::Pkg::CompareExtension { fileName {#}"name of a file whose extension is compared" {ext {}} {#}"The extension to compare against; you must provide the starting dot. Defaults to the info sharedlibextension." } { # ... } \(Whether that style would be regarded as an improvement or not probably depends on one's taste.\) ## Filling in words that will be there at runtime At one point, I found myself wanting to do some calculations with matrices whose elements were polynomials \(with integer coefficients\) of four noncommuting variables _A_, _B_, _C_, and _D_. Having previously implemented some basic algebraic constructions, I could quickly set up a command that implemented arithmetic with such matrices through the two **interp alias**es interp alias {} Z<A,B,C,D> {} \ ::mtmtcl::rings::semigroup_algebra ::mtmtcl::rings::integers::all\ ::mtmtcl::groups::string_free_monoid interp alias {} matrices {} \ ::mtmtcl::matprop::trivial dummy ::Z<A,B,C,D> This is however not a very readable definition even if one is familiar with the commands it uses \(and realises that there is nothing magical about the command name **Z<A,B,C,D>**\), because the way that things appear in this piece of code is visually quite different from the context in which they will appear when evaluated. If instead comment words are inserted as visual placeholders for the missing material, then the overall appearance becomes much closer to that of a script calling these commands. interp alias {} Z<A,B,C,D> {#}method {#}args {} \ ::mtmtcl::rings::semigroup_algebra { ::mtmtcl::rings::integers::all {#}method {#}args } { ::mtmtcl::groups::string_free_monoid {#}method {#}args } {#}method {#}args interp alias {} matrices {#}method {#}args {} \ ::mtmtcl::matprop::trivial dummy { ::Z<A,B,C,D> {#}method {#}args } {#}method {#}args ## "K combinator" In the Tcl community, the _K combinator_ idiom is when you first produce an argument for the main command \(through variable or command substitution\), then evaluate some other command which has beneficial side-effects but whose result is of no interest, and finally evaluate the main command. \(The original K combinator, as found combinatory logic, is more about getting rid of unwanted arguments supplied to a command prefix than about exploiting side-effects, but there is a continuum connecting the two.\) This is most often employed to have a variable release its reference to a Tcl\_Obj, so that the latter becomes unshared and possible for a command to modify directly. **\{\#\}** introduces the new form set stack [lreplace $stack {#}[set stack whatever] end end] of this, providing yet another alternative to such old forms as set stack [lreplace $stack [set stack end] end] set stack [lreplace $stack[set stack ""] end end] set stack [lreplace $stack {*}[set stack ""] end end] Of course, any foo $apa {#}[bar baz] can trivially be rewritten to achieve the same effect using argument expansion instead: foo $apa {*}[bar baz; list] ## Commenting out list elements If a programmer needs to temporarily disable some functionality, then a standard technique is to comment out the corresponding code. However, if the code that needs to be commented out amounts to some elements in a long list \(e.g., a list of commands to [interp expose] in a slave interpreter\) then there is presently no way of commenting out less than the whole command containing that list. Comment words provide a more specific alternative. set tclCommands { after append array binary break case catch cd clock close concat continue dde else elseif encoding eof error eval exec exit expr fblocked fcondict figure fcopy file fileevent flush for foreach format gets glob global history if incr info interp join lappend lassign lindex linsert list llength load lrange lrepeat lreplace lsearch lset lsort namespace open package pid proc puts pwd read regexp regsub rename resource return scan seek set slave socket source split string subst switch tell time trace unknown unset update uplevel upvar variable vwait while {#}{ {#}"Auto-loaded commands" auto_execok auto_import auto_load auto_mkindex auto_mkindex_old auto_qualify auto_reset parray pkg::create pkg_mkIndex tcl_endOfWord tcl_findLibrary tcl_startOfNextWord tcl_startOfPreviousWord tcl_wordBreakAfter tcl_wordBreakBefore } } The same is true in dictionaries. namespace eval ::tcl::info { namespace ensemble create -command ::info -map { exists ::tcl::info::exists globals ::tcl::info::globals locals ::tcl::info::locals vars ::tcl::info::vars args ::tcl::info::args body ::tcl::info::body default ::tcl::info::default commands ::tcl::info::commands procs ::tcl::info::procs functions ::tcl::info::functions cmdcount ::tcl::info::cmdcount complete ::tcl::info::complete script ::tcl::info::script level ::tcl::info::level frame ::tcl::info::frame errorstack ::tcl::info::errorstack patchlevel ::tcl::info::patchlevel tclversion ::tcl::info::tclversion {#}{ {#}"Commented out for bug #nnnnnn." hostname ::tcl::info::hostname sharedlibextension ::tcl::info::sharedlibextension loaded ::tcl::info::loaded library ::tcl::info::library nameofexecutable ::tcl::info::nameofexecutable } coroutine ::tcl::info::coroutine object ::oo::InfoObject class ::oo::InfoClass } } ## Line continuation Comment words also provide an alternative to backslash--newline line continuations, namely as in a command which continues well beyond the normal line width {#}{ } and which one therefore might want to split over two or more {#}{ } lines of code Being several times longer than the simple backslash, this is unlikely to replace it, but there could be cases where one wants to avoid the backslash because that character would be intercepted by something else. # Alternatives Using the author's **docstrip** package <http://tcllib.sourceforge.net/doc/docstrip.html> , one can place comments between any two lines of code \(whether there is a command separator there or not\) and also comment out arbitrary code lines, even if that comes at the price of working with sources that are not raw Tcl code. However, such comments have a tendency to become more of a separate commentary track than an integrated part of the program narrative, and sometimes \(for example to show things that are invisible in the code\) one specifically desires comments to be an integral part of the Tcl code. It is also possible to use **regsub** or something similar to the end of removing comments from a block of code before it is evaluated or put in a variable; instead of having the core language recognise some pieces of code as comments, one preprocesses the code as a string before telling the core that it actually is Tcl code \(or a list/dict/etc.\). Thus instead of \(assuming comment words\): set tclCommands { after append array binary break case catch cd clock close concat continue dde else elseif encoding eof error eval exec exit expr fblocked fcondict figure fcopy file fileevent flush for foreach format gets glob global history if incr info interp join lappend lassign lindex linsert list llength load lrange lrepeat lreplace lsearch lset lsort namespace open package pid proc puts pwd read regexp regsub rename resource return scan seek set slave socket source split string subst switch tell time trace unknown unset update uplevel upvar variable vwait while {#}{ {#}"Auto-loaded commands" auto_execok auto_import auto_load auto_mkindex auto_mkindex_old auto_qualify auto_reset parray pkg::create pkg_mkIndex tcl_endOfWord tcl_findLibrary tcl_startOfNextWord tcl_startOfPreviousWord tcl_wordBreakAfter tcl_wordBreakBefore } } one might write set tclCommands [regsub -all {#[^\n]*\n} { after append array binary break case catch cd clock close concat continue dde else elseif encoding eof error eval exec exit expr fblocked fcondict figure fcopy file fileevent flush for foreach format gets glob global history if incr info interp join lappend lassign lindex linsert list llength load lrange lrepeat lreplace lsearch lset lsort namespace open package pid proc puts pwd read regexp regsub rename resource return scan seek set slave socket source split string subst switch tell time trace unknown unset update uplevel upvar variable vwait while ## Auto-loaded commands # auto_execok auto_import auto_load auto_mkindex auto_mkindex_old # auto_qualify auto_reset parray pkg::create pkg_mkIndex tcl_endOfWord # tcl_findLibrary tcl_startOfNextWord tcl_startOfPreviousWord # tcl_wordBreakAfter tcl_wordBreakBefore } \n] A problem with the latter is that it destroys code line correspondences for [[280]](280.md). The boilerplate code for performing the preprocessing may also need to be inserted far from the actual comment, which discourages use of commenting using such a mechanism. But the main problem with it is that quick fixes like this have a tendency to be half-baked, and would break some otherwise legal code. \(Everything works fine in the example until the day someone needs to insert an element which contains the \# character into the list.\) Since the canonical list-quoting of **\#** is precisely **\{\#\}**, one could \(in analogy with the argument against **\{\}** as expansion prefix\) argue that **\{\#\}something** is too likely to arise as a typo for **\{\#\} something**, which would suggest using some other character than **\#** in the comment prefix. **\\\#** is however a shorter way to list-quote **\#**, so it seems unlikely that **\{\#\}** should be common in manually written code \(unlike **\{\}**, which is very common\). ## Additional alternatives from tcl-core discussion That \(in script words\) the initial substitution round performs variable and command substitution is by several seen as problematic. Only performing backslash substitution there is no great loss, as the only use-case above which relies on other substitutions is the K combinator one that anyway has several alternatives already, but it complicates the implementation by introducing a new parsing mode for scripts \(grab word without variable or command substitution, but with backslash substitution\). In particular, one would have to decide on the exact rules for this; it would probably be best to use the same rules as for command words in lists, which however implies that list {#}[foo bar] would produce a list with one element, namely the string "bar]". A different way of fitting comments into the brace-_something_-brace-_something_ syntax region would be to put the comment material in the first _something_ rather than the second. This could take the form of comment words which begin with **\{\#** and end with **\}\#**, as in $canvas create polygon 0 0 {# left top }# 30 0 {#bend down}# 30 30 \ {# concave part}# 60 30 {#bend up }# 60 0 {# right top }# 90 0 \ {# curving back }# 90 30 45 67 0 30 {# done }# -smooth true \ -width 2 -fill orange -outline green {# Official colours }# \ -tags {button {# for clicking }# buoyant {#affects movement}#} This is similar to Cloverfield's current **\#\{** and **\}\#** comment delimiters, and perhaps also reminicient of C's **/\*** ... **\*/** and Pascal's **\(\*** ... **\*\)**. It should however be stressed that the nesting here would still be that of braces rather than brace\+hash combinations, so {# a b { c }# d {# e f } g }# would be one comment word, not two with a non-comment word **d** in between. Using this syntax could thus lead to false expectations about where a comment ends. A technical disadvantage of **\{\#** and **\}\#** for comment word delimiters is that they make TclFindElement slightly more expensive than for the proposed **\{\#\}** prefix. The reason is that TclFindElement needs to peek at the word after the element it finds to check if that is a comment \(and if so scan past it and peek at the word after that too\). If the comment status of a word can be determined from whether it carries a **\{\#\}** prefix, then it is at worst necessary to peek at the first four characters, but if it matters how the word ends then it might be necessary to parse the whole of the next element in a list before being able to tell that it indeed was not a comment. From a usability point of view, this syntax lends less support for the argument placeholder use-case than the proposed prefix. Donald G Porter has pointed out that this proposal has two functionally unrelated parts, which indeed are easy to discern in the reference implementation: comment words in lists and the like \(changes in TclFindElement\) and comment words in scripts \(all other changes\). It would be possible to propose implementing either one of these parts alone, and the one which is most interesting is then comment words in lists. \(Given just that, one could even use {*}{{#}"Comment goes here"} as an ugly substitute for word comments in scripts.\) However, I believe it is more natural to introduce both together. # Suggested Stylistic Considerations Like ordinary words, comment words come in three varieties: brace-delimited, quote-delimited, and barewords. A style rule which has been used in the above examples is that: * Natural language comment words are of the quote-delimited kind. This is for consistency with the common practice of quote-delimiting text strings within Tcl code, even if said string does not require substitution. * Comment words that serve as placeholders for actual program code are of the bareword variety, e.g. **\{\#\}method**. * Comment words which serve a programmatic purpose, essentially that of the "K combinator", are barewords too. * Comment words which do not fall into any of the above categories, for example those used to comment of a block of words, are brace-delimited. One reason for having a style rule about this is that prettyprinting and syntax colouring utilities _might_ want to highlight these cases differently. Arguably, syntax colouring of Tcl code tends to do _at least as much harm_ as it does good since few engines are able to keep track of enough context to found their claims about the code on reasonably accurate interpretations thereof, but comment words is one of the few things that they might actually manage to get right most of the time, precisely because a comment word is a comment word throughout so many contexts. # Reference Implementation A reference implementation is available as SF Tcl patch \#3522426 <https://sourceforge.net/support/tracker.php?aid=3522426> . It includes some tests, but more could be needed. DGP has also created a branch **tip-401** <http://core.tcl.tk/tcl/timeline?r=tip-401> for it in the core fossil respository; further development is best conducted in the latter. Implementing comment words in lists and the like could be achieved by modifications only in TclFindElement. Comment words in scripts are implemented as argument expansion that does not contribute any word. # Copyright This document has been placed in the public domain. |
Name change from tip/402.tip to tip/402.md.
|
| < | < | | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 402: General Platform UNC Support Author: Jan Nijtmans <[email protected]> State: Draft Type: Project Vote: Pending Created: 16-Jul-2011 Post-History: Discussions-To: Tcl Core list Keywords: Tcl Tcl-Version: 8.7 ----- # Abstract Both Windows and Cygwin interpret paths starting with **//** as a special prefix, indicating that the path has the form: **//server/share/file\_path**. Windows has built-in handling of such paths built-in. UNIX doesn't have this. It could be implemented through a VFS extension, but there is one problem: File normalization on UNIX collapes multiple slashes into a single slash, so this would convert the UNC path into a normal path. This makes it impossible to implement a VFS extension which uses **//** as prefix, implementing connection to a Samba server using the UNC path format. # Rationale At the moment, Cygwin and Windows have built-in a special case that paths starting with double-slash will not be collapsed into a single slash. UNIX does not do that. This change will allow a single uniform format for accessing \(Samba\) shares on external machines using the path format **//server/share/file\_path**. On Windows and Cygwin this already works, because it is built-in Windows functionality. On UNIX a VFS extension could be developed which does the same. # Specification This document proposes: * Extend the special case built-in for Windows and Cygwin to UNIX, so paths starting with double-slash will no longer normalize to paths starting with a single slash. > **POTENTIAL INCOMPATIBILITY** * As **//** becomes a special prefix, the **file split** will return **//** as its first list element when the original path starts with a double slash. # Compatibility On UNIX, this means that paths like **//usr/bin/tclsh** might no longer do what it did earlier, if a VFS exists which uses **//** as path prefix. If no such VFS exists, it will probably still work, only comparing normalized paths will no longer regard **//<foo>** as equal to **/<foo>**. Handling of multiple slashes in other locations of the string will not change. So normalizing **/foo//bar** will still give **/foo/bar**. The most likely cause of multiple slashes appearing in a path is because of appending a file name to a path which already ends with a slash, e.g. set dir "somedir/" set path $dir/filename Of course, the **file join** command does not have this danger: set dir "somedir/" set path [file join $dir filename] On Windows and Cygwin, there is no change in behavior at all. # Alternatives Variations are possible in the handling of paths starting with 3 or more slashes. The current TIP implementation collapes more than 2 slashes to exactly 2 slashes, as the current Windows and Cygwin implementations do. # Reference Implementation A reference implementation is available at <http://core.tcl.tk/tcl> in branch _jn-unc-vfs_. # Copyright This document has been placed in the public domain. |
Name change from tip/403.tip to tip/403.md.
|
| < | < | | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 403: Web Colors for Tk Author: Jan Nijtmans <[email protected]> State: Final Type: Project Vote: Done Created: 17-Jul-2011 Post-History: Discussions-To: Tcl Core list Keywords: Tk Tcl-Version: 8.6 ----- # Abstract This TIP proposes some modifications in the RGB values of various colors as used in Tk, bringing those colors more in line with various W3C standards. # Rationale There is a difference between the color definitions in X11 and the color definitions in Web standards like html and css. For example HTML4 defines the basic color names **aqua**, **fuchsia**, **lime**, **olive**, **silver** and **teal**, which are currently not known to Tk. Making things worse, some colors like **green** and **gray** have a different RGB value in X11 compared to the html4 specification. See: <http://www.w3.org/TR/css3-color/\#html4> # Specification This document proposes: * Add the colors **aqua**, **crimson**, **fuchsia**, **indigo**, **lime**, **olive**, **silver** and **teal** to the list of recognised colors, both for win32 and X11. For X11 it will be built in the wrapper function _TkParseColor_, which is a thin wrapper around _XParseColor_. The RGB values used are those from the above mentioned html4 specification \(6 from the basic colors, 2 from the extended colors\). * Modify the RGB values of **gray/grey**, **green**, **maroon** and **purple** matching the html4 specification. Those 4 colors are the only ones that differ in X11. Applications using those colors will change in visible appearance. > **POTENTIAL INCOMPATIBILITY** # Compatibility On the script level nothing changes, only applications one or more colors from the list **gray**, **grey**, **green**, **maroon** and **purple** will change in visible appearance. A side-by-side visible difference between those 4 colors can be seen at: <http://en.wikipedia.org/wiki/X11\_color\_names\#Color\_name\_clashes> # Alternatives None # Reference Implementation A reference implementation is available at <http://core.tcl.tk/tk> in branch _jn-web-colors_. It contains a test-case _color-1.5_, which checkes the RGB values of all known X11 colors with the above modifications. This test is marked _nonPortable_, simply because I don't know how many older X11 color lists are still in use. On win32, mac and any reasonable recent X11 package, this test passes. # Copyright This document has been placed in the public domain. |
Name change from tip/404.tip to tip/404.md.
|
| < | < | | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 404: Let Message Catalogs get the Locale from their File Name Author: Harald Oehlmann <[email protected]> State: Final Type: Project Vote: Done Created: 17-Jul-2011 Post-History: Discussions-To: Tcl Core list Keywords: msgcat, convention Tcl-Version: 8.6 ----- # Abstract This TIP proposes a mechanism for coupling locales more strongly to the names of the files that define them, an already-recommended practice, so as to make it less error-prone to produce message catalogs. # Rationale Current message catalog files are as follows: * Catalog file name: _<locale>_ **.msg** * Catalog folder: technically any, recommended: msgs in package main folder. Must be specified to the command **mcload**. * Catalog file contents: one command per translated item: msgcat::mcset locale ori ?translation? Example with <locale> equal "de": -de.msg- ::msgcat::mcset de Open Öffnen ::msgcat::mcset de Close Schliessen -eof- The same locale value \(de\) is contained in the file name and in each **mcset** command. This is technically unnecessary and error-prone. I found myself often copying message file contents from one language to the next and not setting the right locale in each **mcset** command. The scope of this TIP is a new command similar to **mcset** which determines the locale from the file name. IMHO it makes no sense to specify the locale of **mcset** commands and the locale in the file name different and thus separately. # Specification ## mc file locale The **mc file locale** is a locale specified by the file name of a message file. Example: > Message catalogue file name: **de\_ch.msg** > mc file locale: de\_ch The package **msgcat** maintains one value, **mc file locale**, with the following properties: * Its initial value is "" \(the root locale\). * Before a message catalog file is sourced by the procedure **::msgcat::mcload**, the **mc file locale** is extracted from the message file name and stored as the current value. * The **mc file locale** may be querried by the command **::msgcat::mcconfig -mcfilelocale**. * The **mc file locale** may also be set by the command **::msgcat::mcconfig -mcfilelocale value**. * The original message filename may _not_ be reconstructed by: **[::msgcat::mcconfig -mcfilelocale].msg**; there can be case differences. The command **::msgcat::mcconfig** is shared with [[399]](399.md). It has a new option **-mcfilelocale**. ## New Commands There are two new commands: * **::msgcat::mcflset** _source_ ?_translation_? * **::msgcat::mcflmset** _list_ These work as: ::msgcat::mcset [::msgcat::mcconfig -mcfilelocale] source ?translation? ::msgcat::mcmset [::msgcat::mcconfig -mcfilelocale] list The command name **mcflset** is an abreviation of: "**m**essage **c'atalogue with **f**ile **l**ocale **set**". # Example Usages The example of the Rationale section above may now be written as: -de.msg- ::msgcat::mcflset Open Öffnen ::msgcat::mcflset Close Schliessen -eof- The locale value **de** only appears in the file name. Further examples are in the tcl wiki msgcat page: <http://wiki.tcl.tk/msgcat> # Reference Implementation See Tcl Feature Request 3544988. <http://sourceforge.net/support/tracker.php/?aid=3544988> # Copyright This document has been placed in the public domain. |
Name change from tip/405.tip to tip/405.md.
|
| < | < | | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | < > | | | | | | | | | | | | | | | | | | | < > | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 405: Add Collecting Loops, the 'lmap' and 'dict map' Commands Author: Trevor Davel <[email protected]> Author: Donal K. Fellows <[email protected]> State: Final Type: Project Vote: Done Created: 31-Jul-2012 Post-History: Keywords: Tcl,mapeach,loop,accumulator Tcl-Version: 8.6 ----- # Abstract The **lmap** command is a collecting loop with the semantics of **foreach**. When the loop begins an accumulator is set to an empty list. In any iteration where the body of the loop completes normally, the result of the body is appended to the accumulator list. The return value for **lmap** is the contents of the accumulator. The **dict map** command is an equivalent collecting loop with the semantics based off **dict for**. # Rationale **lmap** arises from a Tcler's Wiki discussion on higher order functions <http://wiki.tcl.tk/26013> . The construct combines the capabilities of the higher order functions _map_ and _filter_ with the familiarity and expressive power of Tcl's **foreach**. While **lmap** can be implemented in pure Tcl using **uplevel** \(see the Wiki for examples\), substantial performance gains are possible with a bytecode implementation. **dict map** was suggested by DKF on tcl-core \(2012-08-01\) as native dictionary iteration is more efficient that a **lmap** with two variables\). # Proposed Changes A new command **lmap** will be created, with arguments are intentionally very similar to those to **foreach**: > **lmap** _varname list body_ > **lmap** _varlist1 list1_ ?_varlist2 list2 ..._? _body_ The **dict** ensemble will be extended with a new sub-command **map**: > **dict map** \{_keyVar valueVar_\} _dictionary script_ ## The "lmap" Command The **lmap** command implements a loop where the loop variable\(s\) take on values from one or more lists, and the loop returns a list of results collected from each iteration. In the simplest case there is one loop variable, _varname_, and one list, _list_, that is a list of values to assign to _varname_. The _body_ argument is a Tcl script. For each element of list \(in order from first to last\), **lmap** assigns the contents of the element to _varname_ as if the **lindex** command had been used to extract the element, then calls the Tcl interpreter to execute body. If execution of the body completes normally then the result of the body is appended to an accumulator list. **lmap** returns the accumulator list. In the general case there can be more than one value list \(e.g., _list1_ and _list2_\), and each value list can be associated with a list of loop variables \(e.g., _varlist1_ and _varlist2_\). During each iteration of the loop the variables of each varlist are assigned consecutive values from the corresponding list. Values in each list are used in order from first to last, and each value is used exactly once. The total number of loop iterations is large enough to use up all the values from all the value lists. If a value list does not contain enough elements for each of its loop variables in each iteration, empty values are used for the missing elements. The **break** and **continue** statements may be invoked inside body, with the same effect as in the **for** and **foreach** commands. In these cases the body does not complete "normally" and the result is not appended to the accumulator list. ## The "dict map" Command The **dict map** command takes three arguments, the first a two-element list of variable names \(for the key and value respectively of each mapping in the dictionary\), the second the dictionary value to iterate across, and the third a script to be evaluated for each mapping with the key and value variables set appropriately \(in the manner of **lmap**\). In an iteration where the evaluated script completes normally \(_TCL\_OK_\), the script result is put into an accumulator dictionary using the current value of the key variable at that point \(having an unset key variable at that point is an error\); the result of the **dict map** command is that accumulator dictionary. Note that it is a deliberate consequence of the above specification that you can change what key a value is mapped to by altering the key variable during the body of the loop. If any evaluation of the body generates a _TCL\_BREAK_ result, no further pairs from the dictionary will be iterated over and the **dict map** command will terminate successfully immediately. If any evaluation of the body generates a _TCL\_CONTINUE_ result, the current iteration is aborted and the accumulator dictionary is not modified. The order of iteration is the order in which the keys were inserted into the dictionary \(the "natural" iteration order\). \(Note that you can view **dict map** as being to **dict for** what **lmap** is to **foreach**.\) # Examples Square the values of a list: set squares [lmap a $list {expr {$a ** 2}}] Zip lists together: set zipped [lmap a $list1 b $list2 {list $a $b}] Consume several values at once: set sums [lmap {a b} $values {+ $a $b}] Filter a list: set goodOnes [lmap x $values {expr {[isGood $x] ? $x : [continue]}}] Take a prefix from a list: set prefix [lmap x $values {expr {[isGood $x] ? $x : [break]}}] Comparative performance figures: for {set i 0} {$i < 1000000} {incr i} { lappend input [expr { int(rand() * 1000000) }] } # Test the performance of [lmap] time { apply {{} { set accum 0 foreach val [lmap i $::input {expr { $i * 5}}] { incr accum $val } puts $accum }} } 10 # Pure Tcl 'Approach #2' implementation from [http://wiki.tcl.tk/26013] # 1259118.1 microseconds per iteration # C implementation (not bytecode compiled) # 1107894.4 microseconds per iteration # Bytecode compiled # 375085.5 microseconds per iteration Finding the square root of each of the values in a dictionary, filtering out everything that is not a non-negative number \(i.e., outside the domain of the square root operation\): set roots [dict map {k num} $someDict { try { expr {$num ** 0.5} } on error {} { continue } }] Adjusting the global **env** array so that all keys are also present as upper-case keys and lower-case values \(a not-particularly-useful operation\): array set env [dict map {key val} [dict get env] { set key [string toupper $key] string tolower $val }] # Alternatives The name **mapeach** was originally proposed instead of **lmap**. However, since Jim Tcl already supports **lmap** with the same semantics as this TIP proposes, and a pure-Tcl implementation with similar semantics appears on the Wiki <http://wiki.tcl.tk/13920> , this TIP was updated with the change of name. The TIP author favours **lmap**. # Reference Implementation A reference implementation is provided as branch _tip-405-impl-td_. Older revisions are attached to Patch \#3163961 <https://sourceforge.net/support/tracker.php?aid=3163961> . The implementation leverages the existing **foreach** infrastructure to provide bytecode support. A test suite is provided. # Thanks Thanks to Donal Fellows for suggesting a collecting **foreach** and providing examples, and to Steve Bennett for suggesting the name **lmap**. # Copyright This document has been placed in the public domain. |
Name change from tip/406.tip to tip/406.md.
|
| < | | | | | | < | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 406: "C" is for Cookie State: Draft Type: Project Tcl-Version: 8.6 Vote: Pending Post-History: Author: Donal K. Fellows <[email protected]> Created: 01-Aug-2012 ----- # Abstract The "http" package needs cookie support, especially to support complex modern web authentication protocols. This TIP defines a pluggable interface and a TclOO class that implements that interface so that Tcl programmers can control just what is shared and stored, and where. # Rationale and Design Constraints Cookies are a feature of many modern web applications. They're short strings stored in HTTP clients on behalf of servers, and which are then sent back to those servers with further requests to those servers. Often \(but not universally\) these short strings are IDs that are used as database keys to look up a "session object" in a server-side database that holds relevant information; such information can include whether the user has logged in, what color scheme to use in the stylesheet, etc. Of particular relevance to Tcl programmers is the fact that they are often now associated with login information; this means that it is not practical to leave Tcl code without cookie support. Currently, Tcl programs that handle cookies have to do so manually, examining the otherwise-unparsed HTTP headers to see if anything relevant has been set. As the cookie protocol <http://tools.ietf.org/html/rfc6265> is quite complex, it is highly desirable to have a centralized implementation of at least the basic parsing and injection code. The main down-side of adding cookie handling is that definitely increases the ability of web servers to track clients written in Tcl. In particular, there is a danger of cross-application tracking. It is therefore necessary to ensure that the cookie handling mechanism is off by default, and that the locations used to store the cookies are controllable by the Tcl application. # Proposed Change to 'http' Package I propose to add a new configuration option to the _http_ package: > **-cookiejar** _commandPrefixList_ This option \(configurable via **http::config**\), can either be an empty string \(the default\), or it can be a list of words that is a command prefix. An empty string will disable cookie handling: the current _http_ package behavior in relation to cookies \(i.e., ignoring them\) will prevail. However, if a non-empty list of words is supplied, they will be used as if they were a command \(or rather a prefix to be expanded\) in the following ways: ## For Each Cookie Provided by an HTTP Server When a cookie is supplied by an HTTP server, it will be reported to the cookie jar command like this: > \{\*\}_$commandPrefixList_ **storeCookie** _cookieName cookieValue optionDictionary_ The _cookieName_ and _cookieValue_ are relatively self-explanatory; they represent the name/value pair to store. The _optionDictionary_ contains the parsed cookie options, being at least these: hostonly: Boolean; whether the cookie should only ever be returned to the originating host \(if not, it should be sent according to the domain\). This property is always present. httponly: Boolean; whether the cookie ought to be only used with HTTP connections. \(NB: This is unlikely to be something we enforce.\) This property is always present. persistent: Boolean; whether the HTTP server wishes the cookie to persist for longer than the current "session". This property is always present. Non-persistent cookies are expected to never be committed to permanent storage. secure: Boolean; whether the cookie should only be sent on "secure" connections to the HTTP server. \(This typically means "HTTPS is required", but the various cookie specifications are less-than-clear in this area.\) This property is always present. expires: Timestamp; when a persistent cookie will cease to be interesting to the HTTP server that issued it. \(NB: If this is in the past, any matching cookie should be deleted.\) This property is only present if the "persistent" property is true. domain: String; what domains should this cookie be sent to. This property is always present, but may sometimes be the same as the "origin" property; see the "hostonly" property for how to treat this. origin: String; what host did we send the request to that caused this cookie to be generated. This property is always present. path: String; what resource paths within the relevant HTTP servers should a cookie be sent to. This property is always present. The result of this command will be ignored \(so long as it is non-exceptional\). ## When Making an HTTP Request Each time an HTTP request is made, the cookie store is consulted \(prior to the connection being opened\) to find out what cookies should be sent as part of the request, like this: > \{\*\}_$commandPrefixList_ **getCookies** _protocol host path_ The _protocol_ is the name of the protocol scheme that will be used to contact the HTTP server \(typically **http** or **https**\), the _host_ is the server's hostname, and the _path_ is the resource path on that server. The query and fragment parts of the URL are _never_ supplied to the cookie store as part of this request, nor is the port, nor are any user identification credentials \(the cookie specification specifically states that it is a known problem that cookies have _always_ ignored the service port number for the purposes of whether to send the cookie; we therefore duplicate this failure\). The result is treated as a list of keys and values \(i.e., it is expected to be a list with an even number of items in it, with the first key at index 0 and the first value at index 1\) and describes the collection of cookies to send. The _http_ package will manage the formatting of the cookies as part of the request to send. # A Cookie Jar Implementation To go with the above specification, this TIP also describes a TclOO class that will be provided to implement the cookie store side of the protocol. This class will be provided in the **cookiejar** package. The name of the class will be **::http::cookiejar**, and its instances will be cookie stores that participate in the above protocol. The constructor of the class will take an optional argument that names an SQLite database that will be used to store the cookies; if no name is provided, an in-memory database will be used and all cookies will be treated like pure session cookies. The result is that it will be possible to enable cookie handling in a Tcl script using this: package require http package require cookiejar http::config -cookiejar [http::cookiejar new ~/mycookies.db] The **::http::cookiejar** class will also allow configuration of its logging level via the **loglevel** method on the class \(which takes a single argument, the new logging level, or which returns the current logging level if called with no arguments\). Permitted log levels are **error**, **warn**, **info** and **debug**. Log messages will be written by a call to **::http::Log** \(which does nothing by default anyway\). An example of setting the logging level to the \(substantially more verbose\) **debug** level: http::cookiejar loglevel debug The instances of the **::http::cookiejar** class will additionally support the method **forceLoadDomainData** and the method **lookup**. > _instance_ **forceLoadDomainData** This instructs the instance to load \(or reload\) its definitions of what domains may not have cookies set for them. It takes no extra arguments and produces an empty result \(unless an error occurs\). > _instance_ **lookup** ?_host_? ?_key_? This looks up cookies in the store. If neither _host_ nor _key_ are specified, this returns the list hosts for which cookies are defined. If _host_ is specified but _key_ is not, this returns the list of cookie keys for the host \(note that these may be session cookies or durable cookies; this interface does not distinguish\). If both _host_ and _key_ are specified, the value for the particular cookie is returned \(with it being an error if no such cookie is defined\). This method provides no mechanism for setting the value of a cookie or creating a new one. ## Implementation Notes It is worth noting that the current cookiejar package will download a list of "bad" domains \(i.e., domains that correspond to super-registries, such as **com**, **ac.uk** or **tk**\) when a new database is constructed \(provided the cookiejar instance is backed by a database file; in-memory databases never have this part populated by default\). This extensive list of domains <http://mxr.mozilla.org/mozilla-central/source/netwerk/dns/effective_tld_names.dat?raw=1> is a security feature that prevents the setting of cookies for large numbers of hosts at once, but it is belived sufficiently long that it is excessive for supplying as part of the package directly. The degree to which it is necessary to update cookie stores from that list has not yet been studied. The underlying SQLite database is forwarded to the cookiejar instance's interface as the \(default non-exported\) method **Database**; this takes all the normal subcommands of an SQLite _dbcmd_, as documented in <http://www.sqlite.org/tclsqlite.html> . The cookiejar package handles conversion of host names into and out of punycode so that lookups are always performed on canonical names. This is important because there is no guarantee that the encoding of host names will be the same as they are referred to in another context; for example, the list of forbidden domains above is in UTF-8 and not using the IDNA scheme. # Privacy Cookies are often associated in the public mind with problems with privacy. There are two principal mechanisms provided here to mitigate these \(beyond the proposed domain restrictions, which follow recommended Best Practice\): 1. No Tcl interpreter will ever have cookie handling enabled by default. There will always need to be an explicit action taken to turn it on. 2. Applications have to pick the name of their cookie stores when creating and installing them; there is no default. # Copyright This document has been placed in the public domain. |
Name change from tip/407.tip to tip/407.md.
|
| < | < | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 276 277 278 279 280 281 282 | # TIP 407: The String Representation of Tcl Lists: the Gory Details Author: Donal K. Fellows <[email protected]> Author: Kevin Kenny <[email protected]> Author: Don Porter <[email protected]> State: Draft Type: Informative Vote: No voting Created: 06-Aug-2012 Post-History: ----- # Abstract This document explains some of the details behind Tcl lists; it is there to expose documentation that was previously only present as comments in Tcl's source code. # String Representation of Lists The routines [in tclUtil.c] implement the conversions of strings to and from Tcl lists. To understand their operation, the rules of parsing and generating the string representation of lists must be known. Here we describe them in one place. A list is made up of zero or more elements. Any string is a list if it is made up of alternating substrings of element-separating ASCII whitespace and properly formatted elements. The ASCII characters which can make up the whitespace between list elements are: \u0009 \t TAB \u000A \n NEWLINE \u000B \v VERTICAL TAB \u000C \f FORM FEED \u000D \r CARRIAGE RETURN \u0020 SPACE **NOTE:** differences between this and other places where Tcl defines a role for "whitespace". * Unlike command parsing, here NEWLINE is just another whitespace character; its role as a command terminator in a script has no importance here. * Unlike command parsing, the BACKSLASH NEWLINE sequence is not considered to be a whitespace character. * Other Unicode whitespace characters \(recognized by **string is space** or _Tcl\_UniCharIsSpace\(\)_\) do not play any role as element separators in Tcl lists. * The NUL byte ought not appear, as it is not in strings properly encoded for Tcl, but if it is present, it is not treated as separating whitespace, or a string terminator. It is just another character in a list element. The interpretaton of a formatted substring as a list element follows rules similar to the parsing of the words of a command in a Tcl script. Backslash substitution plays a key role, and is defined exactly as it is in command parsing. The same routine, _TclParseBackslash\(\)_ is used in both command parsing and list parsing. **NOTE:** This means that if and when backslash substitution rules ever change for command parsing, the interpretation of strings as lists also changes. Backslash substitution replaces an "escape sequence" of one or more characters starting with \u005c \ BACKSLASH with a single character. The one character escape sequent case happens only when BACKSLASH is the last character in the string. In all other cases, the escape sequence is at least two characters long. The formatted substrings are interpreted as element values according to the following cases: * If the first character of a formatted substring is \u007b { OPEN BRACE > then the end of the substring is the matching \u007d } CLOSE BRACE > character, where matching is determined by counting nesting levels, and not including any brace characters that are contained within a backslash escape sequence in the nesting count. Having found the matching brace, all characters between the braces are the string value of the element. If no matching close brace is found before the end of the string, the string is not a Tcl list. If the character following the close brace is not an element separating whitespace character, or the end of the string, then the string is not a Tcl list. > **NOTE:** this differs from a brace-quoted word in the parsing of a Tcl command only in its treatment of the backslash-newline sequence. In a list element, the literal characters in the backslash-newline sequence become part of the element value. In a script word, conversion to a single SPACE character is done. > **NOTE:** Most list element values can be represented by a formatted substring using brace quoting. The exceptions are any element value that includes an unbalanced brace not in a backslash escape sequence, and any value that ends with a backslash not itself in a backslash escape sequence. * If the first character of a formatted substring is \u0022 " QUOTE > then the end of the substring is the next QUOTE character, not counting any QUOTE characters that are contained within a backslash escape sequence. If no next QUOTE is found before the end of the string, the string is not a Tcl list. If the character following the closing QUOTE is not an element separating whitespace character, or the end of the string, then the string is not a Tcl list. Having found the limits of the substring, the element value is produced by performing backslash substitution on the character sequence between the open and close QUOTEs. > **NOTE:** Any element value can be represented by this style of formatting, given suitable choice of backslash escape sequences. * All other formatted substrings are terminated by the next element separating whitespace character in the string. Having found the limits of the substring, the element value is produced by performing backslash substitution on it. > **NOTE:** Any element value can be represented by this style of formatting, given suitable choice of backslash escape sequences, with one exception. The empty string cannot be represented as a list element without the use of either braces or quotes to delimit it. This collection of parsing rules is implemented in the routine _TclFindElement\(\)_. In order to produce lists that can be parsed by these rules, we need the ability to distinguish between characters that are part of a list element value from characters providing syntax that define the structure of the list. This means that our code that generates lists must at a minimum be able to produce escape sequences for the 10 characters identified above that have significance to a list parser. # Canonical Lists In addition to the basic rules for parsing strings into Tcl lists, there are additional properties to be met by the set of list values that are generated by Tcl. Such list values are often said to be in "canonical form": * When any canonical list is evaluated as a Tcl script, it is a script of either zero commands \(an empty list\) or exactly one command. The command word is exactly the first element of the list, and each argument word is exactly one of the following elements of the list. This means that any characters that have special meaning during script evaluation need special treatment when canonical lists are produced: > \* Whitespace between elements may not include NEWLINE. > \* The command terminating character, \u003b ; SEMICOLON > > must be BRACEd, QUOTEd, or escaped so that it does not terminate the command prematurely. > \* Any of the characters that begin substitutions in scripts, \u0024 $ DOLLAR \u005b [ OPEN BRACKET \u005c \ BACKSLASH > > need to be BRACEd or escaped. > \* In any list where the first character of the first element is \u0023 # HASH > > that HASH character must be BRACEd, QUOTEd, or escaped so that it does not convert the command into a comment. > \* Any list element that contains the character sequence BACKSLASH NEWLINE cannot be formatted with BRACEs. The BACKSLASH character must be represented by an escape sequence, and unless QUOTEs are used, the NEWLINE must be as well. * It is also guaranteed that one can use a canonical list as a building block of a larger script within command substitution, as in this example: set script "puts \[[list $cmd $arg]]"; eval $script > To support this usage, any appearance of the character \u005d ] CLOSE BRACKET > in a list element must be BRACEd, QUOTEd, or escaped. * Finally it is guaranteed that enclosing a canonical list in braces produces a new value that is also a canonical list. This new list has length 1, and its only element is the original canonical list. This same guarantee also makes it possible to construct scripts where an argument word is given a list value by enclosing the canonical form of that list in braces: set script "puts {[list $one $two $three]}"; eval $script > This sort of coding was once fairly common, though it's become more idiomatic to see the following instead: set script [list puts [list $one $two $three]]; eval $script > In order to support this guarantee, every canonical list must have balance when counting those braces that are not in escape sequences. Within these constraints, the canonical list generation routines _TclScanElement\(\)_ and _TclConvertElement\(\)_ attempt to generate the string for any list that is easiest to read. When an element value is itself acceptable as the formatted substring, it is usually used \(CONVERT\_NONE\). When some quoting or escaping is required, use of BRACEs \(CONVERT\_BRACE\) is usually preferred over the use of escape sequences \(CONVERT\_ESCAPE\). There are some exceptions to both of these preferences for reasons of code simplicity, efficiency, and continuation of historical habits. Canonical lists never use the QUOTE formatting to delimit their elements because that form of quoting does not nest, which makes construction of nested lists far too much trouble. Canonical lists always use only a single SPACE character for element-separating whitespace. # Future Considerations When a list element requires quoting or escaping due to a CLOSE BRACKET character or an internal QUOTE character, a strange formatting mode is recommended. For example, if the value "**a\{b]c\}d**" is converted by the usual modes: CONVERT_BRACE: a{b]c}d => {a{b]c}d} CONVERT_ESCAPE: a{b]c}d => a\{b\]c\}d we get perfectly usable formatted list elements. However, this is not what Tcl releases have been producing. Instead, we have: CONVERT_MASK: a{b]c}d => a{b\]c}d where the CLOSE BRACKET is escaped, but the BRACEs are not. The same effect can be seen replacing **]** with **"** in this example. There does not appear to be any functional or aesthetic purpose for this strange additional mode. The sole purpose I can see for preserving it is to keep generating the same formatted lists programmers have become accustomed to, and perhaps written tests to expect. That is, compatibility only. The additional code complexity required to support this mode is significant. The lines of code supporting it are delimited in the routines marked with **\#if COMPAT** directives. This makes it easy to experiment with eliminating this formatting mode simply with "**\#define COMPAT 0**" above. I believe this is worth considering. Another consideration is the treatment of QUOTE characters in list elements. _TclConvertElement\(\)_ must have the ability to produce the escape sequence **\\"** so that when a list element begins with a QUOTE we do not confuse that first character with a QUOTE used as list syntax to define list structure. However, that is the only place where QUOTE characters need quoting. In this way, handling QUOTE could really be much more like the way we handle HASH which also needs quoting and escaping only in particular situations. Following up this could increase the set of list elements that can use the CONVERT\_NONE formatting mode. More speculative is that the demands of canonical list form require brace balance for the list as a whole, while the current implementation achieves this by establishing brace balance for every element. Finally, a reminder that the rules for parsing and formatting lists are closely tied together with the rules for parsing and evaluating scripts, and will need to evolve in sync. # Origin of Document and Copyright Notice This document is based "near-verbatim" on comments in _generic/tclUtil.c_ in the Tcl source code distribution. <http://core.tcl.tk/tcl/doc/trunk/generic/tclUtil.c> Copyright (c) 1987-1993 The Regents of the University of California. Copyright (c) 1994-1998 Sun Microsystems, Inc. Copyright (c) 2001 by Kevin B. Kenny. All rights reserved. This document is made available under the same license as Tcl. [I, Kevin B. Kenny, dedicate any and all copyright interest in TIP #407 to the public domain. I make this dedication for the benefit of the public at large and to the detriment of my heirs and successors. I intend this dedication to be an overt act of relinquishment in perpetuity of all present and future rights to TIP #407 under copyright law.] |
Name change from tip/408.tip to tip/408.md.
|
| < | < | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | < > | < > | | | | | | | | | | | | | | > | 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 | # TIP 408: Allow Any Command for expr Functions Author: Brian Griffin <[email protected]> State: Draft Type: Project Vote: Pending Created: 17-Aug-2012 Post-History: Tcl-Version: 8.7 ----- # Abstract Proposed expansion of what constitutes a function in an **expr** expression. # Rationale: Nested expr Calls The **expr** command in Tcl is the only way to perform math and comparison operations. Tcl's variable and command substitution rules allow for great flexibility, although the syntax does not lead to great readability, especially due to the ordering imposed on substitutions. For example, in the expression: expr {[lindex $data $start] > 4} the command substitution \([...]\) is performed before the expression can be parsed for evaluation, and, in order for the command substitution to be parsed, the variable substitution \($\) must be performed. The consequences of this ordering means that arguments to commands cannot themselves be expressions unless the argument is itself a command substitution involving **expr**. This means, for example, that to compute an index value, **expr** must be recursively called: expr {[lindex $data [expr {$start + 2}]] > 4} However, when using a math function, the command substitution ordering does not apply since the function is part of the expression syntax: expr {pow($x + 2, 2)} It seems reasonable and useful if any Tcl command can be called using function syntax: expr {lindex($data, $start + 2) > 4} The common command substitution pattern has lead many developers to end up writing things like: if {[expr {$a+$b}] > 7} ... In hindsight, such statements look ridiculous, but it works and it follows the same pattern as the **lindex** case above. If subexpressions could be evaluated directly by the enclosing **expr** operations, this would greatly simplify the overall expression and make it more readable and thereby more maintainable, and hopefully, less error prone. The goal here is to reduce the instances of recursive **expr** calls in an expression. It seems overly complex and confusing to read, and to have to use command substitution syntax inside what is already an **expr** operation. # Proposed Changes The proposal is to simply apply normal Tcl command resolution rules to **expr** functions. The one caveat is that **tcl::mathfunc** namespace is always searched first. I see this as a continuation to [[232]](232.md). # Rejected Alternatives This can already be accomplished today by creating alias functions in the **tcl::mathfunc** namespace, but this mechanism is awkward in that: 1. It must be defined beforehand for the set of commands used or intended to be used in expressions, 2. For OO and namespace code, some specialized duplication is also required, and 3. It can lead to confusion when it's not clear why some commands work as functions and others don't. # Proof of Concept \(Thanks and credit to Frédéric Bonnet\) A quick & dirty proof of concept with unknown handlers: proc mathproc {cmd args} { if {[namespace qualifiers $cmd] eq "tcl::mathfunc"} { return [uplevel [list [namespace tail $cmd]] $args] } uplevel [list ::unknown $cmd] $args } namespace unknown mathproc set l [expr {list(1,2,3)}] => 1 2 3 expr {lindex($l,2)} => 3 expr {expr(join($l,"+"))} => 6 # Reference Implementation None currently # Copyright Copyright \(c\) 2012 by GriffinTk This document is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License <http://creativecommons.org/licenses/by-sa/3.0/deed.en_US> . |
Name change from tip/409.tip to tip/409.md.
|
| < | < | | | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 409: UDP in Tcl Author: Alexandre Ferrieux <[email protected]> Author: Colin McCormack <[email protected]> State: Draft Type: Project Vote: Pending Created: 17-Aug-2012 Post-History: Keywords: udp,datagram,message Obsoletes: 391 Tcl-Version: 8.7 ----- # Abstract This TIP adds support for UDP in Tcl, with a pure event approach to packet reception \(as opposed to hijacking the existing channel infrastructure\). # Rationale UDP support is a long-awaited feature in Tcl. Some extensions have traditionally supported it through the channel abstraction. This is of course doable, but there is a non-negligible cost in both complexity and performance due to the impedance mismatch between the "fluid" model behind channels and the "granular" world of datagrams \(where boundaries are significant\). Another discrepancy is the existence of \(per-packet\) metadata, like the source address and port of an incoming UDP packet, which do not fit nicely in the \(per-connection\) options of the channel API \(via **fconfigure**\). Once this mismatch is acknowledged, it is easy to identify a better home for UDP in Tcl: let it be a direct event source \(for the receive side\), just like Tk or Snack. Indeed, hooking a callback for packet reception is a natural fit with Tcl's event-driven tradition, while preserving packet boundaries and easily exposing per-packet metadata. Sending is trivially handled by a direct per-packet call \(but not disguised as a **puts**\). Again, this naturally allows for boundary preservation and metadata specification. This TIP asks for UDP-in-the core for two strong reasons: - it enables another important core feature: asynchronous \(event-driven\) DNS lookups - the C runtime supports it without extra libraries \(unlike USB or Bluetooth\) We then believe that the ubiquity of the need and the lack of external dependencies justify for UDP the first-class status that TCP enjoys \(regardless of the channel vs event models\). Note that an acceptable compromise would be a bundled extension, ie distributed-with-the-core \(in "pkgs/"\). # Specification The new **udp** ensemble hosts three subcommands: **new**, **create**, and **names** > **udp new** ?_options_? > **udp create** _name_ ?_options_? both create an UDP endpoint ; > **udp names** returns the list of existing such endpoints. ## Lifecycle Following the traditions of Tk and Snack, **udp new** and **udp create** return a Tcl command, which takes subcommands implementing the needed verbs. By analogy with the corresponding TclOO constructors, * **new** generates the command name internally, in the **::tcl::udp** namespace * **create** takes an extra _name_ argument providing the target command name, either fully qualified, or relative to the current namespace. An UDP endpoint is thus created by: set u [udp new ...] or udp create foo ... Once created, its configuration can be tweaked by: > $u **configure** _-option_ _value_ and retrieved with > set value [$u **configure** -_option_] or > set fullconf [$u **configure**] To destroy the endpoint, use: > $u **destroy** or, as in Tk, destroy the command: > **rename** $u \{\} or the whole namespace. ## Status of options Among options, a few may only be specified on creation: > - local interface\+port > - \(optional\) connect\(\) target's address\+port > - reuse flag \(described in Advanced Features\) while all the other options may be specified _both_ on creation or through [$u configure]. ## Addresses and Ports The first two creation-only options have the following syntax: > set u [**udp new** ?**-local** _address_port_? ] > set u [**udp new** ?**-remote** _address_port_? ] where _address\_port_ pairs are represented as 2-element Tcl lists. > set address\_port [list $address $port] Addresses can be given either as numeric IP \(v4 or v6\) addresses, or as hostnames; in the latter case, a synchronous DNS resolution is performed before actual use, just like for **socket**. In the case of **-local**, $address can be specified as "\*", meaning INADDR\_ANY, and $port can be 0, asking for the OS to select a free port. Thus a dynamic port on all interfaces can be requested with set u [udp new -local [list * 0]] In case of port 0, after creation of the endpoint, the actual port chosen by the OS can be retrieved with [$u configure]: puts "Local port is: [lindex [$u configure -local] 1]" In the case of **-remote**, both address and port must be fully specified. The semantics, as is well known, is to tell the kernel \(a\) to forbid sending to any other destination, and \(b\) to discard all incoming packets sent by another source. ## Sending a Message Sending is done, unsurprisingly, with the **send** verb: > $u **send** _payload_ ?_dest\_addr\_port_? where _dest\_addr\_port_ is a pair as above. Its blocking semantics is that of the underlying send\(\)/sendto\(\) system calls: it typically returns immediately, though the hardware may buffer the data for some time, and delivery is not guaranteed. The _payload_ is interpreted as a byte array that holds the entire content of the UDP message to send. The destination parameter can be omitted if the endpoint has been created with the **-remote** option \(connected mode\). ## Receiving a message asynchronously Asynchronous \(i.e. event-driven\) message reception is done by specifying a listener callback to **new/create** or **configure**: > $u **configure -listener** _command\_prefix_ Subsequently, when an incoming packet hits Tcl in the event loop, the _command\_prefix_ is called with the endpoint identifier, payload and metadata: > \{\*\}_command\_prefix_ $u _payload_ _metadata\_dict_ where _payload_ is the byte array of the UDP payload and _metadata\_dict_ is a dict containing at least two options: > **-remote** _address\_port_ > **-local** _address\_port_ When read from options or metadata, all address components apart from "\*" are returned in numeric form; no reverse DNS is ever performed. Note that _-local_ may carry more information than a configured _-local_ where the address part is "\*", by identifying which of the system's several interfaces was targeted. Also note that _command\_prefix_ is a single command, possibly with arguments, that will be expanded on invocation \(hence it must be a proper list\); it is \*not\* an arbitrary script as in Tk's **bind_ tradition. When _command\_prefix_ is the empty list \(which is the default\), the notifier gives up interest in the underlying UDP socket; this allows to keep the port bound while letting the OS buffer any incoming packets \(up to a configurable limit\) without any script-level handling, while leaving the event loop active. This is similar to setting a **fileevent** on a channel to the empty string. ## Receiving a message synchronously Synchronous message reception is done with the **recv** verb: > set payload [$u **recv** _metadata_dict_var_] The payload is returned as a byte array, and the variable passed as argument receives the metadata dict just described. ## Advanced features The following few verbs and options control extra IP features that are typically useful in popular UDP applications like media streaming: > $u **configure -sendbuffer** _buffersize_ > $u **configure -receivebuffer** _buffersize_ Set the OS's send \(resp. receive\) buffer sizes to the given values \(in bytes\). > $u **join** _multiaddr_ ?**-source** _sourceaddr_? Joins the multicast group _multiaddr_, optionally using IGMPv3's source membership target _sourceaddr_. > $u **leave** _multiaddr_ ?**-source** _sourceaddr_? Leaves the same multicast group with or without source membership. > set u [**udp new -reuse 1**] Sets the SO\_REUSEADDR socket option, so that multiple processes may bind to the same local port and interface, and receive the same packets. Creation-time only. > $u **configure -ttl** _ttl_ Sets the TTL of subsequent outgoing packets. Some operating systems typically reduce the default TTL to one for multicast packets; this override may thus come in handy. # Rejected Alternatives * Token-based API \(like for channels\) instead of commands: would need extra machinery \(a new Tcl\_ObjType\). Moreover, the command style gives reflection for free: a simple proc can emulate an UDP endpoint, and is compatible with all OO schemes. * Address\+Port pairs as dicts or urls: would hamper performance for no added value * Listener as specific subcommand instead of option: R/W semantics is actually that of an option; a subcommand would preclude the direct specification of the listener on creation ; analogy with the -command of **fcopy**, **http**, or Tk widgets. # Sources of Inspiration This TIP builds on experience with previous attempts at UDP extensions: TclUDP, ceptcl, Duft, along with intensive practice with unpublished work, and borrows ideas from all of them. # Copyright This document has been placed in the public domain. |
Name change from tip/41.tip to tip/41.md.
|
| < | < | | | | | | | | > | | | | | | | | 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 | # TIP 41: Paned Window Tk Widget Author: Eric Melski <[email protected]> State: Final Type: Project Vote: Done Created: 04-Jul-2001 Post-History: Keywords: widget,tk,panedwindow Tcl-Version: 8.4a2 ----- # Abstract This TIP proposes a C-based paned window widget for inclusion in the Tk core. A paned window consists of one or more vertical or horizontal "panes", each pair separated by a movable "sash" and each containing one widget, called a "slave". Paned windows are common in modern graphical user interfaces and should therefore be provided directly by the Tk core. Examples of the widget can be found in Windows Explorer; Netscape Messenger; many email clients; and virtually every graphical World Wide Web browser. # Rationale Tk has long lagged other graphical toolkits in terms of the selection of widgets provided by the toolkit. In order to keep Tk vibrant, useful, and relevant, it is imperative that the widget set be enhanced with widgets which have become commonplace in modern graphical user interfaces. One such widget is the paned window widget. A widget that makes it easy to create robust paned windows should be included with Tk. This paned window widget could be implemented in C or in Tcl; in fact, several Tcl-based paned window widgets already exist. However, these each have quirks, mostly caused by the inability to completely manage the geometry of Tk windows from Tcl \(i.e. there is no way to make calls to things like _Tk\_MaintainGeometry_ or _Tk\_ManageGeometry_\). This issue could possibly be addressed by the creation of a proper megawidget system for Tk, but that goal seems very far from reality right now. If we wait for that system before creating new widgets, it may be too late. In addition, megawidget implementations suffer from "widget bloat" - each paned window widget corresponds to, typically two widgets, plus two or more widgets for each pane after the first. For a Motif-style paned window with two panes, this means five widgets are created \(one frame for the paned window container widget; one frame for each pane; one frame for the sash; one frame for the sash handle\). Even assuming the existence of a proper megawidget system, we may not be able to address the widget bloat issue with a megawidget. A C-based paned window implementation will be able to address both of these issues, and should be more robust, reliable, and lightweight. A C implementation will be able to access Tk's geometry management functions. Also, it will require only one widget for each paned window, |
︙ | ︙ | |||
76 77 78 79 80 81 82 | introduction of a proper "Batteries Included" distribution, but like the proper megawidget system, this seems like a goal far from reality at this time. Another possibility is to distribute the widget with the core, but have it placed in a separate package and namespace. This provides the same level of availability as direct inclusion in the core, but does not actually make the widget part of Tk directly. There are two possible arguments in favor of this approach. First, since this widget will be in its own namespace, future panedwindow widgets could be included without name conflicts. However, if each widget is put in its own namespace, the name conflict has not actually been resolved. The point of contention has simply been moved from the global command space to the global namespace space. Namespaces make sense when grouping blocks of related functions and data, but widgets have only one command. It's just as easy to pick a unique command name as a unique namespace name. The second possible advantage is that the widget could be loaded on demand, rather than automatically being pulled in with Tk. However, most machines that Tk runs on use a virtual memory system. Thus, only those pages/widgets that are actually used will be resident in memory. The benefit of incorporating this widget into the Tk distribution in this manner seem marginal. | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 | introduction of a proper "Batteries Included" distribution, but like the proper megawidget system, this seems like a goal far from reality at this time. Another possibility is to distribute the widget with the core, but have it placed in a separate package and namespace. This provides the same level of availability as direct inclusion in the core, but does not actually make the widget part of Tk directly. There are two possible arguments in favor of this approach. First, since this widget will be in its own namespace, future panedwindow widgets could be included without name conflicts. However, if each widget is put in its own namespace, the name conflict has not actually been resolved. The point of contention has simply been moved from the global command space to the global namespace space. Namespaces make sense when grouping blocks of related functions and data, but widgets have only one command. It's just as easy to pick a unique command name as a unique namespace name. The second possible advantage is that the widget could be loaded on demand, rather than automatically being pulled in with Tk. However, most machines that Tk runs on use a virtual memory system. Thus, only those pages/widgets that are actually used will be resident in memory. The benefit of incorporating this widget into the Tk distribution in this manner seem marginal. ![Example Panedwindow Widget](../assets/41example.png) # Specification The manual entry for the paned window widget is included here: NAME panedwindow - Create and manipulate panedwindow widgets SYNOPSIS panedwindow pathName ?options? STANDARD OPTIONS -background -height -width -borderwidth -orient -cursor -relief See the options manual entry for details on the standard options. WIDGET-SPECIFIC OPTIONS Command-Line Name:-handlepad Database Name: handlePad Database Class: HandlePad When sash handles are drawn, specifies the distance from the top or left end of the sash (depending on the orientation of the widget) at which to draw the handle. May be any value accepted by Tk_GetPixels. Command-Line Name:-handlesize Database Name: handleSize Database Class: HandleSize Specifies the side length of a sash handle. Han- dles are always drawn as squares. May be any value accepted by Tk_GetPixels. Command-Line Name:-opaqueresize Database Name: opaqueResize Database Class: OpaqueResize Specifies whether panes should be resized as a sash is moved (true), or if resizing should be deferred until the sash is placed (false). Command-Line Name:-sashcursor Database Name: sashCursor Database Class: SashCursor Mouse cursor to use when over a sash. If null, sb_h_double_arrow will be used for horizontal panedwindows, and sb_v_double_arrow will be used for vertical panedwindows. Command-Line Name:-sashpad Database Name: sashPad Database Class: SashPad Specifies the amount of padding to leave of each side of a sash. May be any value accepted by Tk_GetPixels. Command-Line Name:-sashrelief Database Name: sashRelief Database Class: SashRelief Relief to use when drawing a sash. May be any of the standard Tk relief values. Command-Line Name:-sashwidth Database Name: sashWidth Database Class: SashWidth Specifies the width of each sash. May be any value accepted by Tk_GetPixels. Command-Line Name:-showhandle Database Name: showHandle Database Class: ShowHandle Specifies whether or not sash handles should be shown. May be any valid Tcl boolean value. DESCRIPTION The panedwindow command creates a new window (given by the pathName argument) and makes it into a panedwindow widget. Additional options, described above, may be specified on the command line or in the option database to configure aspects of the panedwindow such as its default background color and relief. The panedwindow command returns the path name of the new window. A panedwindow widget contains any number of panes, arranged horizontally or vertically, according to the value of the -orient option. Each pane contains one wid- get, and each pair of panes is separated by a moveable (via mouse movements) sash. Moving a sash causes the wid- gets on either side of the sash to be resized. WIDGET COMMAND The panedwindow command creates a new Tcl command whose name is the same as the path name of the panedwindow's window. This command may be used to invoke various opera- tions on the widget. It has the following general form: pathName option ?arg arg ...? PathName is the name of the command, which is the same as the panedwindow widget's path name. Option and the args determine the exact behavior of the command. The follow- ing commands are possible for panedwindow widgets: pathName add slave ?slave ...? ?option value ...? Add one or more slaves to the panedwindow, each in a separate pane. The arguments consist of the names of one or more slave windows followed by pairs of arguments that specify how to manage the slaves. Option may have any of the values accepted by the configure subcommand. pathName cget option Returns the current value of the configuration option given by option. Option may have any of the values accepted by the panedwindow command. pathName configure ?option? ?value option value ...? Query or modify the configuration options of the widget. If no option is specified, returns a list describing all of the available options for path- Name (see Tk_ConfigureInfo for information on the format of this list). If option is specified with no value, then the command returns a list describ- ing the one named option (this list will be identi- cal to the corresponding sublist of the value returned if no option is specified). If one or more option-value pairs are specified, then the command modifies the given widget option(s) to have the given value(s); in this case the command returns an empty string. Option may have any of the values accepted by the panedwindow command. pathName forget slave ?slave ...? Remove the pane containing slave from the panedwin- dow. All geometry management options for slave will be forgotten. pathName identify x y Identify the panedwindow component underneath the point given by x and y, in window coordinates. If the point is over a sash or a sash handle, the result is a two element list containing the index of the sash or handle, and a word indicating whether it is over a sash or a handle, such as {0 sash} or {2 handle}. If the point is over any other part of the panedwindow, the result is an empty list. pathName proxy ?args? This command is used to query and change the posi- tion of the sash proxy, used for rubberband-style pane resizing. It can take any of the following forms: pathName proxy coord Return a list containing the x and y coordi- nates of the most recent proxy location. pathname proxy forget Remove the proxy from the display. pathName proxy place x y Place the proxy at the given x and y coordinates. pathName sash ?args? This command is used to query and change the posi- tion of sashes in the panedwindow. It can take any of the following forms: pathName sash coord index Return the current x and y coordinate pair for the sash given by index. Index must be an integer between 0 and 1 less than the number of slaves in the panedwindow. The coordinates given are those of the top left corner of the region containing the sash. pathName sash dragto index x y This command computes the difference between the given coordinates and the coordinates given to the last sash coord command for the given sash. It then moves that sash the computed differ- ence. The return value is the empty string. pathName sash mark index x y Records x and y for the sash given by index; used in conjunction with later dragto com- mands to move the sash. pathName sash place index x y Place the sash given by index at the given coordinates. pathName slavecget slave option Query a management option for slave. Option may be any value allowed by the slaveconfigure subcommand. pathName slaveconfigure slave ?option? ?value option value ...? Query or modify the management options for slave. If no option is specified, returns a list describ- ing all of the available options for pathName (see Tk_ConfigureInfo for information on the format of this list). If option is specified with no value, then the command returns a list describing the one named option (this list will be identical to the corresponding sublist of the value returned if no option is specified). If one or more option-value pairs are specified, then the command modifies the given widget option(s) to have the given value(s); in this case the command returns an empty string. The following options are supported: -after slave Insert the slave after the slave specified. slave should be the name of a window already managed by pathName. -before slave Insert the slave before the slave specified. slave should be the name of a window already managed by pathName. -height size Specify a height for the slave. The height will be the outer dimension of the slave including its border, if any. If size is an empty string, or if -height is not speci- fied, then the height requested internally by the slave will be used initially; the height may later be adjusted by the movement of sashes in the panedwindow. Size may be any value accepted by Tk_GetPixels. -minsize n Specifies that the size of the slave cannot be made less than n. This constraint only affects the size of the widget in the paned dimension -- the x dimension for horizontal panedwindows, the y dimension for vertical panedwindows. May be any value accepted by Tk_GetPixels. -padx n Specifies a non-negative value indicating how much extra space to leave on each side of the slave in the X-direction. The value may have any of the forms accepted by Tk_GetPixels. -pady n Specifies a non-negative value indicating how much extra space to leave on each side of the slave in the Y-direction. The value may have any of the forms accepted by Tk_GetPixels. -sticky style If a slave's pane is larger than the requested dimensions of the slave, this option may be used to position (or stretch) the slave within its pane. Style is a string that contains zero or more of the characters n, s, e or w. The string can optionally contains spaces or commas, but they are ignored. Each letter refers to a side (north, south, east, or west) that the slave will "stick" to. If both n and s (or e and w) are specified, the slave will be stretched to fill the entire height (or width) of its cavity. -width size Specify a width for the slave. The width will be the outer dimension of the slave including its border, if any. If size is an empty string, or if -width is not specified, then the width requested internally by the slave will be used initially; the width may later be adjusted by the movement of sashes in the panedwindow. Size may be any value accepted by Tk_GetPixels. pathName slaves Returns an ordered list of the widgets managed by pathName. RESIZING PANES A pane is resized by grabbing the sash (or sash handle if present) and dragging with the mouse. This is accom- plished via mouse motion bindings on the widget. When a sash is moved, the sizes of the panes on each side of the sash, and thus the widgets in those panes, are adjusted. When a pane is resized from outside (eg, it is packed to expand and fill, and the containing toplevel is resized), space is added to the final (rightmost or bottommost) pane in the window. # Reference Implementation The widget described here has already been implemented, with documentation and a full test suite. The widget is included with the Vu widget extension, part of the _tktable_ SourceForge project at <http://tktable.sourceforge.net> # Notes Suggestions for possible future enhancements: * Allow specification of a weight for each pane, similar to the -weight option supported by grid, to be used when allocating space from a resize to panes in the widget. * Allow a bindable image to be placed on the window sash, a la Netscape's Messenger, or Java Swing, to allow one-click expand and collapse of the pane. * Integrate with the -setgrid option such that if a pane contains a -setgrided widget, the sash can only be moved in grid size steps. None of these are prohibited by the current design, and could be implemented at a later date as enhancements to the widget. # Copyright This document has been placed in the public domain. |
Name change from tip/410.tip to tip/410.md.
|
| < | < | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 410: Three Features of scan Adapted for binary scan/format Author: Andreas Leitgeb <[email protected]> State: Draft Type: Project Vote: Pending Created: 26-Aug-2012 Post-History: Tcl-Version: 8.7 ----- # Abstract This proposal specifies three new features for **binary scan** and **binary format** that already exist similarly for **scan**, namely: **\#** for consuming a count-value from the parameter list \(like "**scan %\***"\), **p** for writing current position to a consumed parameter variable \(like "**scan %n**"\) and returning a single parsed value if no parameter is left. # Rationale Experience with **binary format** and **binary scan** indicates that there are some features of **scan** which it would be highly desirable to have. In particular, the ability to take an item length as a separate parameter, to store the current location, and to return a **single matched value** when last variable is not supplied would all be highly desirable. Different symbols for some of the operations have had to be chosen, as both "\*" and "n" already exist and have a different meaning for **binary scan** and **binary format**. Also, unlike with _scan_. no list of values shall be returned \(except for a single counted conversion\), but instead only one extra conversion character allowed. Experience with scan shows that people tend to forget about the list-layer and use _[scan "08" %d]_ directly as a number, which, while safe for integers, is just the wrong thing to do. The TIP-Author believes that these are all rather "low hanging fruit". If this turns out not to be the case, then any controversial one of these features shall be moved to its own TIP. # Proposal A "**\#**" \(number sign\) at a place in the format-string where a number or a "**\***" is currently allowed, shall consume one item from the parameter list and interpret it as a number. It shall only occur after a conversion specifier that accepts trailing numbers. The parameter consumed for "**\#**" is the one _after_ the parameter used for the conversion specifier itself, as the "**\#**" follows that specifier. A new conversion specifier "**p**" shall not accept a trailing count and consume one item from parameter list and interpret it as the name of a local variable into which to store the current cursor-position. No data is consumed for **binary scan** and no data produced for **binary format**. A **binary scan** with a format-string that contains **one** data conversion specifier **more** than variable parameters shall return the remaining converted value \(or an empty string if the last conversion wasn't successful\). ## Details A "**p**"-conversion is not counted. In classic usage with variable parameters, the return value of **binary scan** gives only the number of real data conversions, thus not counting "**@**", "**x**", "**X**" or "**p**". A "**\#**" given as count will always imply a list of values written to the variable, even if the value is "1" and the list is of length 1. A negative value could change the direction for relative movements "**x**" and "**X**", and is treated as 0 in all other cases. A non-numeric value \(including the empty string!\) given for a "**\#**" causes the **binary** command to return an error, just like garbage in the format string would. It is explicitly not intended to get single-value behaviour with "**\#**" and empty string, nor have the separate count-value contain an asterisk or further conversion characters. # Further Ideas Eventually, as a special case for **binary scan**, the following idiom shall be allowed outside of the basic specification: binary scan "\0\0\0\x2A" "I p" pos returns 42 and then writes 4 to variable pos. While the idiom would be quite practical, there is a risk of reader's confusion about which value would be written and which returned, despite unambiguous definition. Also, this one might turn out to be less than trivial to implement, as it would require some lookahead to reserve the remaining parameter for "p", not for "I" that is currently at hand. # Examples # pad out 12 nuls, then set cursor to 0, write an # int, record position, then write another int. set data [binary format "x# @0 I p I" 12 1 pos 42] --> data: "\0\0\0\1\0\0\0\x2A\0\0\0\0" pos: 4 # set cursor position from value of first param, scan # three items from the data and write them to the # next three parameter variables, then write new cursor # position to next parameter variable. binary scan $data "@# Iss p" $pos beI leS1 leS2 pos --> beI: 42 leS1:0 leS2:0 pos:12 # 4 is value for "#", no further param, thus return # result for "I" set val [binary scan $data "@# I" 4] --> val: 42 # error case: more than one conversion to return set val [binary scan $data "@# II" 4] --> error: "not enough arguments for all format specifiers" # extra "further ideas" feature: set val [binary scan $data "@# I p" 4 pos] --> val: 42 pos: 8 # Rejected Alternatives For a format string "**a\#**", one could have argued to use first parameter for the count and second for the conversion target, as that would be the order of relevance \(count is needed before the resulting value is even generated\). I think, this is a bikeshedding issue, and any choice is a good choice, so I went with order of occurrence, thus "**a\#**" expects the target variable first, and the count second. It would be possible to use "**@**" without a count instead of "**p**", but I consider it dangerous, when a previous error turns into overwriting of variables. I consider a typo "**@ 42 ...**" to be common enough to not want to give it a new unexpected meaning and side-effect. # Copyright This document has been placed in the public domain. |
Name change from tip/411.tip to tip/411.md.
|
| < | < | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | < > | | | | | | < > | | | < > | | | | < < < > > > | | | | < > | | | | < > | | | < < > > | | | | | < > | | | | | | | | > | 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 | # TIP 411: Improved Channel Introspection via "chan info" Author: Pawel Salawa <[email protected]> State: Draft Type: Project Vote: Pending Created: 31-Aug-2012 Post-History: Tcl-Version: 8.7 ----- # Abstract This document describes new subcommand for **chan**, **chan info**, that provides a unified interface to deeper introspection of information about a particular channel. # Rationale When working with Tcl channels sometimes it happens that we got the channel, but we don't know if it's a file channel, socket, or reflected channel. This information can be very useful. Also some additional information, depending of the channel type, like file path for file channel, host and port for sockets \(it's already available, but could get unified within new **chan** subcommand\), or any metadata provided by reflected channels. An example where it could be used is the package with an API that accepts just a channel on input call and the inside routines need to do something with the file \(in file system\), so they have to learn the name of the file related to given channel. # Specification A new subcommand for **chan** is introduced: > **chan info** _channelId_ Also a new optional command is introduced for reflected channels API: > _cmdPrefix_ **chaninfo** _channelId_ ## The info Subcommand of chan The **chan info** command will take a single mandatory argument, _channelId_, which will be the name of a channel to retrieve information about. This operation will always fail in a safe interpreter. The result of the new **chan info** command would be a dictionary with following keys always present: type: indicating a type of channel. Possible values are "**file**", "**socket**", "**process**" \(result of [**open** "\|..."]\), empty string \(in case of channel that doesn't support this information\), or any custom type, depending of refchan implementations. This is a mandatory key. The remainder of the keys are optional and depend on the type. For **file** channels, the dictionary shall include these: path: full, normalized path to the file, including the file name. new: boolean value indicating whether file already existed while opening, or it was created. For **socket** channels, the dictionary shall include these: host: peer hostname, or local hostname for listening socket. This is partially equivalent to getting the first value returned by [**chan configure** _channelId_ **-peername**] for connected sockets. port: peer port, or listening port \(for listening socket\). This is partially equivalent to getting the third value returned by [**chan configure** _channelId_ **-peername**] for connected sockets. side: one of the following: "**client**", "**accepted**", or "**listening**". For **process** channels, the dictionary shall include these: cmdline: copy of the command passed to **open**. pid: PID of a spawned process, as produced by **pid**. Any key could be produced by other channel types, notably including reflected channels. ## The chaninfo Operation of Reflected Channel Implementations The **chaninfo** subcommand of a reflected channel implementation command returns a dict that is provided in response to a **chan info** request. If the dictionary does not include the mandatory **type** member, the reflected channel baseline implementation will add it and set it to **refchan**. It is an error to return a non-dictionary. Since reflected channels are free to set the type to anything, they can simulate standard channels, like "**file**", as well as create completely new types. If the operation is not supported, the baseline implementation will treat it the same as if the operation returned an empty dictionary. # Internals Channel structure in Tcl core would require another API level indicating channels that have a function returning an "info" dict. All core channels are expected to migrate to this level, although it's possible to stay at current API version - it will just cause the **type** in **chan info** dict to be the _typeName_ field of the channel's _Tcl\_ChannelType_ structure, with no additional keys in the dict. # Examples This is a a pure Tcl implementation of file type channel, so it supports new information in **chan info**: oo::class create filechan { variable path fd created filemode constructor {fpath mode} { set filemode $mode set path $fpath } method initialize {ch mode} { set exists [file exists $path] set fd [open $path $filemode] set created [expr { [file exists $path] && !$exists}] return "initialize finalize watch read seek chaninfo" } method finalize {ch} { ::close $fd my destroy } method watch {ch events} { foreach event [list read write] method [list readable writable] { if {$event in $events} { fileevent $fd $method [list chan postevent $ch $event] } } } # Must be present on a readable channel method read {ch count} { ::read $fd $count } # This method is optional, but useful for the example below method seek {ch offset base} { ::seek $fd $offset $base } method chaninfo {ch} { dict create type file path $path new $created } } proc openfile {file mode} { # lets not bother of what modes should be passed to [chan create], # it's just an example... chan create [list read write] [filechan new $file $mode] } set fd [openfile "myfile.txt" r] puts [chan info $fd] close $fd # Reference Implementation <http://sqlitestudio.pl/tcl/patches/tip-411-chan\_info.patch> Patch made against 8.6.0 \(just before final release\). # Copyright This document has been placed in the public domain. |
Name change from tip/412.tip to tip/412.md.
|
| < | < | | | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | < < > > | | | | | | | | | | | | | | | < < < < | > > > > | | | | | | | | | | | < > | | | < | > | | | | | | | | | | | | | | > | 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 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 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 | # TIP 412: Dynamic Locale Changing for msgcat with On-Demand File Load Author: Harald Oehlmann <[email protected]> Author: Harald Oehlmann <[email protected]> State: Final Type: Project Vote: Done Created: 27-Mar-2012 Post-History: Keywords: Tcl,localization,msgcat Obsoletes: 399 Tcl-Version: 8.6 ----- # Abstract This TIP adds dynamic locale switching capabilities to the **msgcat** package. # Rationale ## Dynamic Locale Switching Within a multi-language application like a web-server, one may change the locale quite frequently, for example if users with different locales are requesting pages. Unfortunately, this does not fit well with the model adopted by the msgcat package, which assumes that all code follows this sequence: 1. Set locale list: **mclocale** _locale_ 2. Load language files with other package load: **mcload** _msg-folder_ 3. Translate strings: **mc** _key args..._ Note that if the locale should be changed after other packages are loaded, one must restart at step 2. This requires reloading all packages which is mostly not practical. The aim of this TIP is to extend the package by dynamic locale change capabilities. msgcat will reload any missing message catalog files of all currently loaded packages on a locale change. In addition, any package may register to get informed to a locale change. Other packages may do changes to reflect the locale change like rebuilding the GUI. This TIP compares to [[399]](399.md) that the package is able to load message catalog files on demand, e.g. specially on a locale change. ## package locale If the clock command gets called with the argument "-locale", the locale is changed using msgcat::mclocale. After processing, the initial value is restored. The package keeps track, which locales where already used and calls msgcat::mcload for any new locale. The locale is restored after processing. This is an implementation of dynamic locales but conflicts with the new features described above. Other packages may be informed to change the locale and may trigger expensive operations like a rebuild of the GUI. In consequence, each package may define a package locale which is independent of the default locale. # Overview of the proposed solution Proposed changes in brief: ## Dynamically load message catalog files if the locale is changed by mclocale locale, the message file load process is executed for every present package. ## Package locale A package may install a package local locale which is independent to the global locale. ## Locale change callback A callback may be registered to get informed about the change of locale. A use case is to refresh a GUI if the locale changed. ## Non message file operation A program may use message files to issue mcset commands or may issue them by other means, if the message catalogs are, for example, stored in a data base. Each package may register a callback to get informed that a certain locale should be loaded and may issue the corresponding mcset commands. ## Package mcunknown A package may have a certain way to provide translations for message keys not included in the message catalog. Thus, it may register an own package message unknown callback to provide a translation. # Specification ## Package Equals Client Namespace A client package is a package which uses msgcat. A unique namespace is required for each client package. Within msgcat, namespace and package is always connected. Up to now, the msgcat package used this namespace as an identifier to store the catalog data of a certain package. This is now extended to additional properties which are stored for a package. ## Package locale A package locale may be used by a package instead the default locale set by msgcat::mclocale. A package may choose to use a package locale or the default locale. ## Default and Package State Some state values \(like the locale\) are available as default \(global\) values. In addition, each package may choose to use a package locale state. The used naming is: default state: valid for all packages which do not set a package state. package state: only valid for one package if it has set a package state. The following state values are present as default state and may be set individually per package: The locale like "de\_ch". The preferences property is a list of locales in their preference order and is automatically computed from locale. Example locale = "de\_ch" -> preferences = "de\_ch de \{\}". The loadedlocales state value is the list of currently loaded locales. ## Default State The following standard methods exist to get or set the default state: ### msgcat::mclocale The default locale. It may be read using msgcat::mclocale. It may be set using msgcat::mclocale locale. This command is extended, that the message catalogs of all missing locales for all packages not having set a package state are loaded. ### msgcat::mcpreferences Get the default preferences \(derived from the default locale\). ### msgcat::mcloadedlocales The following new command may be used to deal with the default state: > **msgcat::mcloadedlocales** _subcommand_ _?locale?_ The parameter locale is mandatory for the subcommand present. The following subcommands are available: ### Subcommand "get" Get the list of current loaded locales ### Subcommand "present" Returns true, if the given locale is loaded ### Subcommand "clear" The list of currently loaded locales is set to mcpreferences and all message catalog keys of packages without a package locale set and with locales not in mcpreferences are unset. ## Package Configuration The package configuration of the calling package may be changed using the following new command: > **msgcat::mcpackagelocale** _subcommand_ ?_locale_? The parameter locale is mandatory for the subcommands set and present. Available subcommands are: ### Subcommand "set" Set or change the package locale. The global state values are copied, if there were no package locale set before. The package locale is changed to the optional given new package locale. ### Subcommand "get" Return the package locale or the default locale, if no package locale set. ### Subcommand "preferences" Return the package preferences or the default preferences, if no package locale set. ### Subcommand "loaded" The list of locales loaded for this package is returned. ### Subcommand "isset" Returns true, if a package locale is set. ### Subcommand "unset" Unset the package locale and use the default state for the package. Load all message catalog files of the package for locales, which were not present in the package loadedlocales list and are present in the default list. ### Subcommand "present" Returns true, if the given locale is loaded ### Subcommand "clear" Set the current loaded locales list of the package to preferences and unset all message catalog keys of the package with locales not included in the package preferences. ## Package Configuration Options Each package may have a set of configuration options set to invoke certain actions. They may be retrieved or changed with the following new command: > **msgcat::mcpackageconfig** _subcommand option_ ?_value_? Available subcommands are: get: Get the current value of the option or an error if not set. isset: Returns true if option is set. set: Set the given value to the option. May have additional consequences and return values as described in the option section. unset: Unset the option. Available options are: ### Package Option "mcfolder" This is the message folder of the package. This option is set by mcload and by the subcommand set. Both are identical and both return the number of loaded message catalog files. Setting or changing this value will load all locales contained in the preferences valid for the package. This implies also to invoke any set loadcmd \(see below\). Unsetting this value will disable message file load for the package. If the locale valid for this package changes, this value is used to eventually load message catalog files. Message catalog files are always sourced in the namespace of the package registering the value. ### Package Option "loadcmd" This callback is invoked before a set of message catalog files are loaded for the package which has this property set. This callback may be used to do any preparation work for message file load or to get the message data from another source like a data base. In this case, no message files are used \(mcfolder is unset\). See chapter callback invocation below. The parameter list appended to this callback is the list of locales to load. If this callback is changed, it is called with the preferences valid for the package. ### Package Option "changecmd" This callback is invoked when a default local change was performed. Its purpose is to allow a package to update any dependency on the default locale like showing the GUI in another language. Tk may be extended to register to this callback and to invoke a virtual event. See the callback invocation section below. The parameter list appended to this callback is mcpreferences. All registered packages are invoked in no particular order. ### Package Option "unknowncmd" Use a package locale mcunknown procedure instead of the standard version supplied by the msgcat package \(msgcat::mcunknown\). The called procedure must return the formatted message which will finally be returned by msgcat::mc. A generic unknown handler is used if set to the empty string. This consists in returning the key if no arguments are given. With given arguments, format is used to process the arguments. See chapter callback invocation below. The appended arguments are identical to mcunknown. ### Callback Invocation Callbacks are invoked under the following conditions: the callback command is set, the command is not the empty string, the registration namespace exists. Any error within the callback stops the operation which invoked the callback. This might be surprising, as the error might be in another package. ## Test if Message Key is Set Message catalog keys may be expensive to calculate and thus may be set on demand. The following new procedure returns false, if mc would call mcunknown for a key: > **msgcat::mcexists** _src_ There are two options, to limit the key search to just the current namespace \(don't search in parent namespaces\) and just the current locale \(don't search the preferences but the first item\): > **msgcat::mcexists** ?**-exactnamespace**? ?_-exactlocale_? _src_ ## forget package A package may clear all its keys and state using the new command: > **msgcat::mcforgetpackage** ## Locale and Preferences Format Locales set by mcset may eventually not correspond to the current preferences, as the preferences are treated as follows: put to lower case, remove any multiple "\_" and any "\_" at the beginning or at the end of the locale. It is proposed, that: the locale and the first preferences element is always identical to the lowercase passed locale, any multiple "\_" are seen as one separator. Example: preferences of locale "sy\_\_cyrl\_win" current preferences: "sy\_cyrl\_win sy\_cyrl sy" proposed preferences: "sy\_\_cyrl\_win sy\_\_cyrl sy". Alternatively, all locales may normalized using the upper algorithm, which felt heavy in computation with little gain. # Example Usage ## Example from TIP \#399 Imagine an application which supports the current user language and French, German and English. An external package tp is used. The package uses msgcat and installs itself during the package require tp call: package require msgcat msgcat::mcload [file join [file dirname [info script]] msgs] An implementation of the application with the current msgcat 1.5.0 would require the following initialization sequence: package require msgcat package require np and the following code to change the locale to French: package forget np msgcat::mclocale fr package require np Using the extension of this TIP, one may load as usual: package require msgcat package require np and to change to french locale: msgcat::mclocale fr The first time, a locale is required, all corresponding message files of all packages which use msgcat get loaded. This might be a heavy operation. If a locale is reactivated \(and the message catalog data was not cleared\), it is a quick operation. Without this TIP, it is computational expensive \(if possible, as many packages are not reloadable or a reload may disturb current processing, e.g., by forcing the closing of sockets, etc.\). ## Change with No Need to Come Back If it is certain that a locale is changed and the then obsolete data is of no use, one may clear unused message catalog items: msgcat::mclocale fr msgcat::mcloadedlocale clear ## Use a Callback to be Notified About a Locale Change Packages which display a GUI may update their widgets when the locale changes. To register to a callback, use: namespace eval gui { msgcat::mcpackageconfig changecmd updateGUI proc updateGui args { puts "New locale is '[lindex $args 0]'." } } % msgcat::mclocale fr fr % New locale is 'fr'. ## To Use Another Locale Source than Message Catalog Files If locales \(or additional locales\) are contained in another source like a data base, a package may use the load callback and not mcload: namespace eval db { msgcat::mcpackageconfig loadcmd loadMessages msgcat::mcconfig loadedpackages\ [concat [msgcat::mcconfig loadedpackages] namespace current] proc loadMessages args { foreach locale $args { if {[LocaleInDB $locale]} { msgcat::mcmset $locale [GetLocaleList $locale] } } } } ## Use a package locale The reference implementation also contains a changed clock command which uses a package locale. Here are some sketches from the implementation. First, a package locale is initialized and the generic unknown function is activated: msgcat::mcpackagelocale set msgcat::mcpackageconfig unknowncmd "" If the user requires the week day in a certain locale, it is changed: clock format clock seconds -format %A -locale fr and the code: msgcat::mcpackagelocale set $locale return [lindex [msgcat::mc DAYS_OF_WEEK_FULL] $day] ### Returns "mercredi" Some message-catalog items are heavy in computation and thus are dynamically cached using: proc ::tcl::clock::LocalizeFormat { locale format } { set key FORMAT_$format if { [::msgcat::mcexists -exactlocale -exactnamespace $key] } { return [mc $key] } #...expensive computation of format clipped... mcset $locale $key $format return $format } # Reference Implementation See Tcl fossil tag msgcat\_dyn\_locale [[1]](1.md). # Compatibility Imagined incompatibilities: If packages call mcload multiple times with different folders, the data was currently appended. This is still the case, but only the last folder is used for any reload. The property **mcfolder** may be transformed to a list to cover this case. The return value of mcload \(file count\) may be much higher as there may be loaded much more files. I suppose, this value is only used by the test suite to verify functionality and is not for big general use. Message files may not be aware, that they may be loaded at any moment and not only after their own **mcload**. I suppose, this is the biggest issue but I think, there is no alternative. Message files do not get reloaded any more, if a second mcload is issued with the same path argument. Package which temporary change the default locale trigger any callback and may lead to user visible side effects. # Issues Known issues: Packages might not be aware of a locale change and may buffer translations outside of **msgcat**. Packages should not buffer msgcat messages if they are used in a dynamic locale application \(like tklib tooltip does for example\). The clock command currently has a small dynamic patch for msgcat implemented. This must be removed in favor to new msgcat features due to the temporarily change of the default locale. # Extensions Expose the function to calculate the preference list from a given locale. Load a message catalog file for a given locale without changing the default/package locale. Methods isloaded to check if a locale is currently loaded. Access message catalog with specified namespace, locale and search behavior. # Alternatives The alternative is the former [[399]](399.md), but that is problematic because the list of locales must be known before any package load. The additional complexity of this TIP is a justifiable trade-off against the greatly improved flexibility in the loading and locale selection order. # Copyright This document has been placed in the public domain. |
Name change from tip/413.tip to tip/413.md.
|
| < | < | | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 413: Unicode Support for 'string is space' and 'string trim' Author: Jan Nijtmans <[email protected]> State: Final Type: Project Vote: Done Created: 08-Oct-2012 Post-History: Discussions-To: Tcl Core list Keywords: Tcl Tcl-Version: 8.6 ----- # Abstract This TIP is in fact a re-consideration of [[318]](318.md), in that it attempts to define, once and for all, for which characters **string is space** should return 1 and which characters **string trim** should trim. # Rationale Intuitively, **string is space** and **string trim** should treat the same characters as space, but currently that's not the case, even after the implementation of [[318]](318.md). The unicode standard advanced to version 6.2 now \(at the time of this writing\), but also Java and .NET have their own views on what whitespace should be. Let's try to learn from them. ## Defining the Tcl Space Set The NUL character has the function as string separator, which could be considered in the same group as LINE SEPARATOR \(U\+2028\) and PARAGRAPH SEPARATOR \(U\+2029\). It's a very useful character to be stripped. It even had the Whitespace property in Unicode 2.0. The problem with considering this character as space is that its visible representation is not specified, it even should not occur in normal text. Therefore, it is not in the "Tcl space set", but it is very useful to let it be stripped by **string trim**. The Unicode standard changed in time, which resulted in whitespace characters being removed \(deprecated\) and added. The _String.Trim\(\)_ method in .NET 3.5 stripped zero width space \(U\+200B\) and zero width no-break space \(U\+FEFF\) from strings, but later .NET versions don't do that any more. The "Tcl space set" should not depend on that: If characters are deprecated in future Unicode versions, and because of that Whitespace properties are changed, they will not be removed from the "Tcl space set". But if new whitespace characters are added in future Unicode standards, they will be added to the "Tcl space set" as well, influencing both **string is space** and **string trim**. The 3 characters that are in the "Tcl space set" but not in the current Unicode whitespace set are discussed now. Most obvious is zero width no-break space \(U\+FEFF\), which is a very useful character to be stripped, as it is used now as Byte Order Mark \(BOM\). It has no visible representation, and - in fact - no meaning at all within Tcl, as Tcl is UTF-8 internally already. It should not occur anywhere else in the string, but in the past it could as being a zero-width no-break space. It had the _White\_Space_ property in Unicode 2.0, but later versions of Unicode do not; the use of the BOM as a space was deprecated. When the use as space was deprecated for \(U\+FEFF\), another character was put forward as replacement for it: word joiner \(U\+2060\). As this character has no visible representation, and has no meaning at all when at the start or the end of a string, it makes sense to include it in the "Tcl space set" as well, the more because its predecessor had the _White\_Space_ property. Finally, zero width space \(U\+200B\), had the _White\_Space_ property in Unicode 3.0. In the current Unicode Charts it is still listed as being a space, even though the White\_Space property was removed later. Therefore it should be in the "Tcl space set" as well. # Specification This document proposes: * For the ASCII set, **string is space** stays as is. **string trim** will be modified to trim all characters for which **string is space** returns 1, augmented with the NUL character. This means that NUL, VT and FF will be added to the set. This is a **potential incompatibility**. * For characters outside ASCII, the Unicode **White\_Space** <http://www.unicode.org/Public/6.2.0/ucd/PropList.txt> property forms the basis of what **string is space** and **string trim** consider being space. But 3 characters are added to the set: zero with space \(U\+200B\), word joiner \(U\+2060\) and zero width no-break space \(U\+FEFF\) \(i.e., the BOM\). The **string trimleft** and **string trimright** commands will also be modified, as they track **string trim**. # Compatibility For the ASCII set, the only change is the addition of 3 characters to **string trim**. For Unicode there are more changes, but all added characters are either rarely used, either intuitively expected to be trimmed by **string trim**. I don't think that any code will be adversely affected by this change, it will probably fix more bugs than that it breaks any existing code. # Alternatives 1. NUL could be added to **string is space**, but that would be in conflict with what POSIX _isspace\(\)_ function does. 2. NUL could be left out of the **string trim** set. 3. Additional characters I considered being part of the set: break permitted here (U+0082) no break here (U+0083) zero width joiner (U+200C) zero with non-joiner (U+200D) > Those are clearly useful characters to be stripped, as they have no meaning and no visible appearance at the beginning or end of a string. But they are not spaces, so it would diverge the two commands. # Reference Implementation A reference implementation is available in the Tcl fossil repository on the _tip-318-update_ branch <https://core.tcl.tk/tcl/timeline?r=tip-318-update> . # Copyright This document has been placed in the public domain. |
Name change from tip/414.tip to tip/414.md.
|
| < | < | | | | | | | | > | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 414: Add (back) Tcl_InitSubsystems as Public API Author: Brian Griffin <[email protected]> Author: Jan Nijtmans <[email protected]> State: Draft Type: Project Vote: Pending Created: 15-Oct-2012 Post-History: Tcl-Version: 8.7 ----- # Abstract The ability to initialize just the lower level Tcl subsystems used to be part of the public API, now it is no longer exposed. This TIP proposes that it be re-exposed. # Rationale Some parts of Tcl's API are useful in portable applications even without creating a Tcl interpreter; examples of this include Tcl\_Alloc and \(most of\) the Tcl\_DString-related functions. In order to use these functions correctly, the Tcl library _must_ be initialized, yet the function for doing so - Tcl\_InitSubsystems \(currently TclInitSubsystems\) - was removed from Tcl's API; using Tcl\_FindExecutable instead feels incorrect as we're not seeking to make the name of the executable available to Tcl scripts. # Proposed Change A new function Tcl\_InitSubsystems, similar to the internal TclInitSubsystems, should be exposed as alternative to Tcl\_FindExecutable in Tcl's C API. This will _not_ be a part of the Stub API; it is not intended to ever be used from an initialized stubbed environment, as it is meant to be used prior to the stub table being available. It has a single argument, _panicProc_. When NULL, the default panic function is used. The full signature is: > EXTERN const char \* **Tcl\_InitSubsystems**\( Tcl\_PanicProc \*_panicProc_\); The return value of _Tcl\_InitSubsystems_ is the Tcl version. # Reference Implementation A reference implementation is available in the **initsubsystems** branch. <http://core.tcl.tk/tcl/info/3c9828933f> # Copyright This document has been placed in the public domain. |
Name change from tip/415.tip to tip/415.md.
|
| < | < | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | < < > > | | | | | | | | | | | | | | | | | | | | | | < > | | | | | | | | | | < > | | | | | | > | 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 | # TIP 415: Enable Easy Creation of Circular Arc Segments Author: Simon Geard <[email protected]> State: Draft Type: Project Vote: Pending Created: 16-Oct-2012 Post-History: Keywords: Tk Tcl-Version: 8.7 ----- # Abstract Creating a segment of a circular arc is unnecessarily difficult using the **canvas** arc. This TIP proposes a simple extension of the syntax to support the creation of circular arc segments in a natural way. A similar extension to support the more general elliptical arc segments is outside the scope of this TIP. # Rationale There is scope to enhance arc creation to make it much more useful as was shown by a recent discussion on news:comp.lang.tcl. The proposal here is the simplest enhancement to enable creation of circular arc segments from a single parameter. # Proposal Enhance arc creation to support a new **-height** option > _canvas_ **create arc** _x1 y1 x2 y2_ **-height** _h_ ?_options_? The new option **-height** _h_ causes the specified coordinates _x1 y1_ and _ x2 y2_ to be interpreted as the start and end points of the arc's chord. The value of _h_ is the \(canvas\) distance of the arc's mid-point from the chord with the sign of _h_ determining the direction of the arc: _h_ > 0 => clockwise _h_ < 0 => anticlockwise If _h_ != 0 then the options _-start_ and _-extent_ are ignored \(because they are calculated internally for a given _h_\). Any non-zero value of _h_ defines a unique arc. If _h_ = 0 \(exactly\) the option is ignored and the command is processed as if it wasn't present. In addition > _canvas_ **itemcget** _tagOrId_ _--height** will always return 0. This behaviour enables introspection without complications. A consequence is that > _canvas_ **itemconfigure** _tagOrId_ _--height** _0_ is a no-op. # Example The following code shows the creation of arcs using the new method, copying them onto another canvas and using a **scale** widget to dynamically control the arcs # Callback for modifying the arcs' h value proc deltaHeight {h} { global c global arcList foreach {i hp hm} $arcList { $c itemconfigure a_$i -height [expr {$h*$hp}] $c itemconfigure b_$i -height [expr {$h*$hm}] } } # Create the canvas and its duplicate set c [canvas .c -width 700 -height 700 -bg grey] set cc [canvas .cc -width 700 -height 700 -bg grey] pack $c $cc -fill both -expand 1 -side left # Pretty colours array set colours {0 red 1 yellow 2 green 3 cyan 4 blue 5 magenta} # A slider with which to adjust h set lh 1; # Initial setting for scale set s [scale .s -from 0.1 -to 15 -resolution 0.1 -variable lh -orient vertical -length 700 -command deltaHeight] pack $s -side right -fill y # Create the arcs for {set i 1} {$i <= 24} {incr i} { set col [expr {$i % 6}] set hp [expr {$i*10}] set hm [expr {-$i*10}] lappend arcList $i $hp $hm $c create arc 300 200 400 400 -height [expr {$i*10}] -outline $colours($col) -style arc -tags [list aa a_$i] $c create arc 300 200 400 400 -height [expr {-$i*10}] -outline $colours($col) -style arc -tags [list aa b_$i] } # Serialize set fh [open "ccopy.tcl" w] foreach id [$c find withtag aa] { puts $fh "\$cc create arc [$c coords $id] \ -height [$c itemcget $id -height]\ -start [$c itemcget $id -start] \ -extent [$c itemcget $id -extent] \ -outline [$c itemcget $id -outline] \ -style [$c itemcget $id -style]" } close $fh # Create copy from serialization source "ccopy.tcl" # Reference Implementation A reference implementation for the functionality is available. # Copyright This document has been placed in the public domain. |
Name change from tip/416.tip to tip/416.md.
|
| < | < | | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 416: New Options for 'load': -global and -lazy Author: Christian Delbaere <[email protected]> Author: Jan Nijtmans <[email protected]> Author: Jan Nijtmans <[email protected]> State: Final Type: Project Vote: Done Created: 31-Oct-2012 Post-History: Tcl-Version: 8.6 ----- # Abstract This TIP proposes enhancing the Tcl **load** command with the additional options **-global** and **-lazy**. It is implemented on top of [[357]](357.md), by defining a meaning to the **flags** parameter already defined there. # Rationale Platforms that use the _dlopen\(\)_ function to Tcl **load** shared modules at runtime provide options to control how the library is loaded: * global vs. local symbol scoping * lazy vs. now symbol resolution Currently, Tcl's **load** command has hard coded defaults for these options and they cannot be overridden within a Tcl script. This imposes constraints on the internal implementation of the modules intended to be loaded into the interpreter. This is especially problematic for modules that provide Tcl scripting bindings for existing C\+\+ APIs. Often, the C\+\+ APIs make assumptions about the availability and scoping of their symbols. Tcl binding packages for C\+\+ APIs are often created by a different development group than the one that created the original C\+\+ API. Because the two groups are independent, the C\+\+ API maintainers will not always be open or able to change their code to fit the requirements to be loaded into a scripting language. A common problem occurs when the same static variable is present in two different Tcl modules. For some applications, the variable is meant to be shared across modules \(global scoping\), while in other applications, the variable must have its own value within each module \(local scoping\). If the wrong scoping is chosen, the underlying code will not work correctly; rather it will yield strange bugs and / or crashes. Also in the domain of Tcl bindings for C\+\+ APIs: it's convenient for the binding package maintainers to have binary compatibility between one version of the Tcl API and several versions of the C\+\+ API. The **-lazy** flag for Tcl's load command will provides the feature necessary for this flexibility, since it can be used to defer missing symbol errors. So, users can often continue to run their scripts as long as they restrict themselves to calling only commands where the symbols are available. Of course, some applications work best when **load** is called with **-global** and some work best without it. The same can be said for **-lazy**. By providing these options, Tcl will allow programmers to choose the best fit for their application. # Specification In [[357]](357.md), the _Tcl\_LoadFile_ is given as: > EXTERN int **Tcl\_LoadFile**\( Tcl\_Interp \*_interp_, Tcl\_Obj \*_pathPtr_, const char \*_symbols_[], int _flags_, void \*_procPtrs_, Tcl\_LoadHandle \*_handlePtr_\); The meaning of the _flags_ parameter is not defined in TIP \#357, except that the current value should be 0. This TIP defines the meaning of the first two bits of this parameter: #define TCL_LOAD_GLOBAL 1 #define TCL_LOAD_LAZY 2 Any combination \(logical or\) of those two bits can be given to the _flags_ parameter. The remaining bits are meant for future extension and are currently ignored, but should be set to 0. The **load** command will get two new options: Current specification: > **load** _fileName_ ?_packageName_ ?_interp_?? Recommended specification: > **load** ?**-global**? ?**-lazy**? ?**--**? _fileName_ ?_packageName_ ?_interp_?? # Discussion Not all platforms may support library loading to a degree required for this TIP functionality. In that case, the additional options just act as if they were not there. The reference implementation works on most modern UNIX systems and MacOSX, which use _dlopen\(\)_ or _NSLinkModule\(\)_. Windows does not allow lazy symbol resolution or global scoping, so the options have no effect on Windows. The **load** command will determine the use of the new form by checking if more than one argument is given and the first argument starts with a **-**. This should not affect any existing extensions, as dynamic library filenames beginning with **-** are rare. Note that use of the **-global** or **-lazy** option may lead to crashes in your application later \(in case of symbol conflicts resp. missing symbols\), which cannot be detected during the **load**. So, only use this when you know what you are doing, you will not get a nice error message when something is wrong with the loaded library. # Examples Load a module with the defaults \(local scoping, "now" resolution\) load module.so Load the module with global scoping and "now" resolution load -global module.so Load the module with global scoping and lazy resolution load -global -lazy module.so # Reference Implementation A reference implementation is available in the **frq-3579001** branch; see <https://core.tcl.tk/tcl/timeline?r=frq-3579001> # Copyright This document has been placed in the public domain. |
Name change from tip/417.tip to tip/417.md.
|
| < | < | | | | | | | | > | | | | | | | | | | | | | > | 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 | # TIP 417: Use Explicit Option Names for "file tempfile" Author: Christophe Curis <[email protected]> State: Draft Type: Project Tcl-Version: 8.7 Vote: Pending Created: 16-Nov-2012 Post-History: Keywords: Tcl, future expansion, extensibility ----- # Abstract This TIP proposes altering the way in which optional arguments are specified to **file tempfile** \(see [[210]](210.md)\) to make them easier to understand and extend in the future. # Rationale The current documentation for **file tempfile** states that there are two optional arguments using a fixed order. This has some limits: * it is not possible to use the second argument without the first * being an infrequently-used function, having a fixed order implies that a look to the manual page will be obligatory to make sure of the order * this inhibits potential for any future expansion of the command. Switching to option/value format will make the optional arguments easier to understand. # Proposal The syntax of the command would be changed to: > **file tempfile** ?_options..._? with supported _options_: * **-namevar** _variable_: Specifies a variable for receiving the file name. * **-template** _template_: Defines a template for the file name. This syntax would allow: * easy extension in the future, as any option name can be added, * ability to use any of the options in any order, * an explicit syntax making the code easier to read and understand. # Reference Implementation No implementation is available now, but the change is probably not complex; the priority have been placed on raising the subject before the release of the final 8.6 version of Tcl. # Copyright This document has been placed in the public domain. |
Name change from tip/418.tip to tip/418.md.
|
| < | < | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 418: Add [binary] Subcommands for In-Place Modification Author: Jeff Rogers <[email protected]> State: Draft Type: Project Vote: Pending Created: 27-Aug-2012 Post-History: Keywords: Tcl,binary data Tcl-Version: 8.7 ----- # Abstract This TIP proposes adding new subcommands to the **binary** to better enable parsing and manipulation of binary values. # Rationale The **binary** command efficiently deals with creating new objects or completely parsing existing ones, but it does not handle modifying existing binary objects or parsing them a little bit at a time. A few new subcommands would greatly improve the performance of these operations on large objects. ## Variable vs. Value While it will be possible to implement these modification operations as standard copy-on-write operations taking a value instead of a variable name, I believe this would result in copying unless the well-known but still clumsy technique of unsetting the variable after reading it \(i.e., [K $x [set x {}]]\) is used. This TIP is intended to fix this by providing a more convenient and simpler-to-use mechanism which also admits more efficient implementation. # Specification Two new core subcommands are proposed: **binary edit** modifies an existing byte array "in place"; and **binary scanshift** parse data from a byte array and removes the data that was parsed. The intent is that additional commands can be built on top of these in library code. The existing **binary** commands already make use of an internal cursor; that notion is extensively used by these new commands. ## Binary Edit > **binary edit** _varName formatStr_ ?_value value ..._? This is similar to **binary format** except that the initial value of the new byte array is an existing object stored in a variable rather than an array of nulls. Format specifiers in _formatStr_ are as in **binary format** except: * fixed-width format specifiers \(e.g., **c**, **s**, **i**\) that do not have enough values in their corresponding argument \(importantly, if they have 0 values\) move the cursor by the appropriate width. * New **z** and **Z** format specifiers are introduced that move the cursor forward or backward in the binary string without writing anything and consume no arguments. **Z** is a synonym for "X", provided for symmetry. A count of "**\***" for the "**z**" format moves the cursor to the end of the existing object. After the format string and all arguments have been processed, the length of the string is adjusted to end at the current cursor position. Thus, a format string that starts with "z\*" will append to the existing value, and one that ends with "z\*" will keep the length the same. ## Binary Scanshift > **binary scanshift** _varName formatStr_ ?_var var var ..._? This works like **binary scan** except that after the format string has been processed and all variables assigned to, all data in the string before the ending location of the cursor is discarded. Thus, binary scanshift bvar c byte1 binary scanshift bvar c byte2 binary scanshift bvar c byte3 Will put the first 3 bytes of the binary _$bvar_ into _byte1_, _byte2_, and _byte3_, with _bvar_ being subsequently three bytes shorter \(the missing bytes being the first three\). This is useful to avoid keeping a separate external cursor variable that must be incremented and re-used on each iteration. ## Additional Library Commands Suggested additional library commands are **poke** and **append**. The arguments to **binary poke** will be: > **binary poke** _varName index formatStr_ ?_var ..._? This moves the cursor to a specified index, then overwrite with the specified format string. Implemented as binary edit varName "@${index} $formatStr z*" var ... The arguments to **binary append** will be: > **binary append** _varName formatStr_ "?_var ..._? This appends the given formatted data to an existing var. Implemented as binary edit varName "z* $formatStr" ?var ...?" # Implementation Notes Efficient implementation of the "**scanshift**" subcommand requires a new "offset" field in the ByteArray structure and any operations that read the object \(particularly duplicating it and updating the string representation\) need to be aware of this field. All external interfaces should be unaffected, as the ByteArray structure type is private to tclBinary.c, And since it's internal, EIAS is not violated. When extending an existing byte array with the "**edit**" subcommand, care should be taken with memory allocation to avoid repeated _realloc\(\)_ and _memcpy\(\)_ operations. It is a reasonable assumption that a given byte array will be extended repeatedly or not at all beyond the initial creation. So a memory allocation strategy is to allocate the exact length initially \(i.e., when adjusting the size from 0 to non-zero\) and allocating double the requested length subsequently a typical allocation-doubling strategy should work well. A double allocation should not be needed for an initial extension \(i.e., extending from 0 to some length\) as that is typically the case when a binary object is first created, and most binary objects will probably not be extended; but once extended it is reasonable to prepare for more of the same. After numerous "**scanshift**" operations there will be wasted space at the beginning of the memory allocated for the data. One strategy for keeping this under control would be to move the live data to the beginning of the allocated space when the offset is larger than the live data, so that the memory could be copied without worrying about overlap; and this would also leave the allocation size at roughly double the live data size. # Reference Implementation Forthcoming. # Copyright This document has been placed in the public domain. |
Name change from tip/419.tip to tip/419.md.
|
| < | < | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 419: A New Command for Binding to Tk Events Author: Jeff Rogers <[email protected]> State: Draft Type: Project Vote: Pending Created: 28-Aug-2012 Post-History: Tcl-Version: 8.7 ----- # Abstract This TIP proposes a more modern mechanism for binding callbacks to Tk's events. # Rationale The Tk **bind**' command passes details about an event to a callback script by doing a textual substitution of percent markers. This has worked well for years, however most recent code prefers to use command prefixes to which set arguments are appended rather than scripts which are evaluated. This TIP proposes such an approach for tk event binding. # Specification A new command, "tkevent" is introduced with the following syntax: > **tkevent** _tag_ _sequence_ _cmd_ The _tag_ and _sequence_ arguments are the same as used in the **bind** command. The _cmd_ is evaluated by appending a single argument which is a dictionary containing the event details. The implementation of _cmd_ can retrieve details of the event using that dictionary. Bindings created by **tkevent** are compatible with those created by **bind**. When a sequence is bound to a tag using **tkevent**, it replaces any previous binding, and vice versa. Appending to a binding with "bind tag sequence \+script" may not work as expected. The possible keys in the dict passed to the handler are: serial above button count detail focus height window keycode mode override_redirect place state time width x y character border_width delta send_event keysym keysym_num property root subwindow type window xroot yroot These keys are intended to be be the same as the options to **event generate** where applicable. Not all values are legal for all event types; where a key is not legal for an event type, it will not be present in the dictionary when the _cmd_ bound to that event is evaluated. # Reference Implementation A sample implementation of these commands in pure tcl is available at <http://wiki.tcl.tk/tkevent> # Cross-Compatibility with Bind Except for the "\+script" feature, **bind** and **tkevent** support identical functionality, and either could be implemented in terms of the other. If **bind** as a core command was dropped in favor of **tkevent**, it could be provided as a library implementation. # Copyright This document has been placed in the public domain. |
Name change from tip/42.tip to tip/42.md.
|
| < | < | | | | | | | > | | | | | 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 | # TIP 42: Add New Standard Tk Option: -clientdata Author: Bryan Oakley <[email protected]> State: Withdrawn Type: Project Vote: Pending Created: 05-Jul-2001 Post-History: Tcl-Version: 8.5 ----- # Abstract This TIP proposes to add a new standard option, -clientdata, for all Tk widgets. # Rationale Many modern and not so modern widget toolkits provide a way to attach programmer defined data to a widget. Tk lacks such a feature. The only way to accomplish a similar feat today is by storing data in a global or namespace variable keyed by widget name. This doesn't lend itself very well to general purpose library routines. One example of how this could be used is in prototyping additional widget functionality. For example, [[39]](39.md) requests a new option for each widget that enables a widget to declare that it is part of a larger compound widget. One potential use of this new flag is in the Tk library code that handles keyboard traversal. With the option proposed in this TIP, it would have been quite simple to prototype the necessary changes at the script level, making it easier to validate the utility of the requested change in TIP \#39, and to provide a reference implementation of the affected library procedures. Another example use of this flag would be in the development of a graphical interface builder such as SpecTcl or Visual Tcl. With applications that let you create widgets interactively, it is often convenient to attach metadata directly to the widget. For example, |
︙ | ︙ | |||
53 54 55 56 57 58 59 | ... and the list goes on. The bottom line is, it adds flexibility that can be leveraged in many ways. Impact on the core is minimal since it merely requires the storage and retrieval of information. And the mechanism is already in place; we merely need to define a slot in the widget data structure to store the information. | | | | | | | | | | | | | | > | 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 | ... and the list goes on. The bottom line is, it adds flexibility that can be leveraged in many ways. Impact on the core is minimal since it merely requires the storage and retrieval of information. And the mechanism is already in place; we merely need to define a slot in the widget data structure to store the information. # Specification Suggested wording for the _options_ man page \(which, I suspect, can be greatly improved upon\): Command-Line Name: -clientdata Database Name: clientData Database Class: ClientData > _Specifies programmer defined data to be associated with the widget. The Tk libraries do not use this information or require the information to be in any particular format. It is purely for use by the application._ # Lame Joke Did you hear the one about the three legged dog that went into a saloon, jumped up on the nearest stool, banged his good foot on the bar, and with a steely-eyed glare said "I'm lookin' for the man that shot my Paw!"? # Notice of Withdrawal This TIP was Withdrawn by the TIP Editor following discussion on the tcl-core mailing list. The following is a summary of reasons for withdrawal: > Perhaps some of the ideas behind these TIPs should be incorporated into some new TIP on making megawidget support better, but none of these TIPs really stand on their own. \(38 isn't a good idea, since alteration of the bindtags for all widgets of a class at once is a bad idea, and it is better when rolling your own megawidget classes to put the setting up of the bindtags in there. 39 and 42 just clash with each other as soon as you have two different codebases trying to use a single widget.\) # Copyright This document has been placed in the public domain accompanied with only a small and very personal amount of fanfare. |
Name change from tip/420.tip to tip/420.md.
|
| < | < | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | < > | < > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 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 | # TIP 420: 'vexpr', a Vector Expression Command Author: Sean Woods <[email protected]> Author: Andreas Kupries <[email protected]> State: Draft Type: Project Vote: Pending Created: 15-Nov-2012 Post-History: Tcl-Version: 8.7 ----- # Abstract This TIP proposes to add a new command to Tcl for manipulating vectors and related mathematical objects. The command, **vexpr**, will provide C-optimized implementations of generally useful scalar, 2D, 3D and affine transforms. **vexpr** is a complement to **expr**, and expects to take in vector arguments and return vector results. # Rationale With the interest expressed in the community by [[363]](363.md), I am concerned about the introduction of non-scalar results from **expr** \(and parts of the language the use **expr**\). As the goal of that TIP is to introduce vector math operations, a less ambitious, but arguable equally effective technique could be to introduce a dedicated command. In particular, one designed from the ground up to handle the intricacies of vector operations. **vexpr** is a vector expression parser. It operates using reverse-polish notation \(like an HP calculator.\) Each argument is pushed onto the stack, and when a command is detected, they are popped off the stack. The result of the command is pushed onto the stack in their place. Why? Well mostly for ease of implementation. Partly because there is no PEMDAS equivalent order of operation for matrices and vectors. Once I go through an example or two, it should be a little clearer. # Examples To add \{1 1 1\} and \{2 2 2\} I run the following command: vexpr {2 2 2} {1 1 1} + > 3.0 3.0 3.0 Remember though, we are working with a stack. Items are popped on the stack in a first-in first-out fashion. While for addition it doesn't matter what order we do things, subtraction does care. vexpr {1 1 1} {2 2 2} - > 1.0 1.0 1.0 vexpr {2 2 2} {1 1 1} - > -1.0 -1.0 -1.0 While with 2 arguments and an opcode this seems silly, imagine a complex operation with several steps. Here we are going to model a robot arm with 3 joints. Each "arm" is one unit long, and when one joint bends, the rest follow suit. _unbent_ (A) - (B) - (C) _bent_ (C) | (B) / (A) Code: # Positions of the joints set A_pos {0.0 0.0 0.0} set B_pos {1.0 0.0 0.0} set C_pos {2.0 0.0 0.0} # Rotations of the joints set A_rot {0 0 45} set B_rot {0 0 45} set b_transform [vexpr \ $A_pos $B_pos - \ affine_translate \ $A_rot radians \ affine_rotate \ affine_multiply] > { 0.707 0.707 0.0 -0.707} {-0.707 0.707 0.0 0.707} { 0.0 0.0 1.0 0.0} { 0.0 0.0 0.0 1.0} set b_real [vexpr $B_pos $b_transform vector_transform] > 0.707106 0.707106 0.0 set c_transform [vexpr \ $C_pos $B_real - \ affine_translate \ load affine_multiply \ $B_rot radians \ affine_rotate \ affine_multiply] > { 0.0 1.0 0.0 0.707} {-1.0 0.0 0.0 2.293} {0.0 0.0 1.0 0.0} {0.0 0.0 0.0 1.0} set c_real [vexpr $C_pos $c_transform vector_transform] > 0.0 2.0 0.0 If you aren't familiar with 3D math and affine transformations, that may look overly complicated, but as you can see each **vexpr** call is packed with commands. You can plainly see that after 2 45 degree bends, our "C" point comes to rest at 0.0,2,0 after completing a 90 degree bend. # Operations Note that all arguments that are not one of these operation words are instead treated as values to push onto the evaluation stack. ## affine\_multiply > AFFINE AFFINE -> AFFINE Multiplies 2 4x4 matrices. Used to combine 2 affine transformations. Note: Some affine transformations need to be performed in a particular order to make sense. ## affine\_rotate > VECTOR -> AFFINE Converts a "vector" of 3 angles \(Xrotation Yrotation Zrotation\) into an affine transformation. NOTE: the angles should be in radians. ## affine\_scale > VECTOR -> AFFINE Converts a scale vector \(Xscale Yscale Zscale\) into an affine transformation. Note: 1.0 1.0 1.0 = No scaling. 2.0 2.0 2.0 = Double the size. 0.5 0.5 0.5 = Half the size. ## affine\_translate > VECTOR -> AFFINE Converts a displacement vector \(X Y Z\) into an affine transformation ## cart\_to\_cyl > VECTOR -> VECTOR Converts a cartesian vector to cylindrical coordinates ## cart\_to\_sphere > VECTOR -> VECTOR Converts a cartesian vector to spherical coordinates ## cross > VECTOR VECTOR -> VECTOR Performs the cross product of two vectors ## copy > ANY -> ANY ANY Copies the top of the stack, pushing it onto the stack. ## cyl\_to\_cart > VECTOR -> VECTOR Converts a vector in cylindrical coordinates to cartesian coordinates ## cyl\_to\_degrees > VECTOR -> VECTOR Converts a cylindrical vector in radians to degrees. ## cyl\_to\_radians > VECTOR -> VECTOR Converts a cylindrical vector in degrees to radians. ## degrees > VECTOR -> VECTOR Converts a vector or scalar in radians to degrees. ## dot > VECTOR VECTOR -> SCALAR Produces the dot product of two vectors. ## dT > \(None\) -> SCALAR Pushes the value of dT into the stack. ## identity > \(None\) -> AFFINE Pushes the identity matrix onto the stack. ## load > \(None\) -> ANY Pushes the last value stored by STORE onto the stack. ## pi > \(None\) -> SCALER Pushes the value of PI onto the stack. ## radians > VECTOR -> VECTOR Converts a vector or scalar in degrees to radians. ## setDT > SCALAR -> \(None\) Pops the current stack value and stores it in the dT variable. ## sphere\_to\_cart > VECTOR -> VECTOR Converts a vector in spherical coordinates to cartesian coordinates. ## sphere\_to\_degrees > VECTOR -> VECTOR Converts a spherical vector in radians to a spherical vector in degrees. ## sphere\_to\_radians > VECTOR -> VECTOR Converts a spherical vector in degrees to a spherical vector in radians. ## store > ANY -> ANY Stores the top of the stack internally for later use. The value stored remains at the top of the stack. ## vector\_add > VECTOR VECTOR -> VECTOR Adds 2 vectors, which must be of the same length. ## vector\_length > VECTOR -> SCALAR Produces the length of a vector. ## vector\_scale > SCALAR VECTOR -> VECTOR Scales a vector by a scalar ## vector\_subtract > VECTOR VECTOR -> VECTOR Subtracts one vector from another. ## vector\_transform > AFFINE VECTOR -> VECTOR Transforms a vector using an affine matrix. # Implementation A test implementation for **vexpr** is available as an TEA extension, and can be downloaded <http://www.etoyoc.com/tclmatrix3d> . At this point in time, the goal is adding **vexpr** as a standalone command. ## Limits **vexpr** converts all arguments to an array of 16 double precision elements; only the item left on the top of the stack is converted back into a Tcl list. The "stack" itself has a hard-coded limit of 32 elements. \(It is implemented as an array.\) Exceeding the stack size will cause the command to throw a Tcl error. # Copyright This document has been placed in the public domain. |
Name change from tip/421.tip to tip/421.md.
|
| < | | | | | | < | | | > | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 421: A Command for Iterating Over Arrays State: Draft Type: Project Tcl-Version: 8.7 Vote: Pending Post-History: Author: Karl Lehenbauer <[email protected]> Author: Donal K. Fellows <[email protected]> Created: 28-Nov-2012 ----- # Abstract This TIP proposes an efficient mechanism for iterating over the contents of a large array. # Rationale Tcl currently provides three main mechanisms for iterating over the contents of an array, but none are quite perfect when dealing with a large array. * **array get** is simple to use \(especially with a two-variable **foreach**\) but requires the contents of the array to be effectively duplicated; even with the use of the Tcl\_Obj system for value reference management, this is an expensive operation. * **array names** \(with a simple **foreach**\) is also relatively simple to use, but requires producing a list whose size is the same as the number of elements of the array. \(This is half the size that would be required with **array get**, but can still be large.\) * **array startsearch** et al. provide a memory-efficient general iteration mechanism, but in a way that is rather difficult to use. It is also subject to significant hazards if the array is modified during iteration \(a particular problem for the global **env** array, as that is regenerated on almost any read\). The authors propose that there be a new subcommand of **array** which allows for efficient iteration over an array's elements. # Proposed Change There should be a new command, **array foreach**, that has this syntax: > **array** **foreach** _arrayName_ \{_keyVar_ _valueVar_\} _body_ This will iterate internally over the elements of the array called _arrayName_ in array-iteration order \(i.e., the same as that used by the other **array** subcommands\), setting the variable _keyVar_ to the name of the element and the variable _valueVar_ to the content of the element before evaluating the script _body_. The result will be the empty string \(excepting errors, **return**, etc.\) and any contained **break** and **continue** will have their normal interpretation as loop control operations. # Implementation Not yet... # Copyright This document has been placed in the public domain. |
Name change from tip/422.tip to tip/422.md.
|
| < | < | | | | | | | | > | | | | | | | | | | | | | | | | | | < | > | | | | | | | | | | < | > | | | | | > | 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 | # TIP 422: Don't Use stdarg.h/va_list in Public API Author: Jan Nijtmans <[email protected]> State: Draft Type: Project Vote: Pending Created: 02-Jan-2013 Post-History: Tcl-Version: 9.0 Keywords: Tcl, API removal, varargs ----- # Abstract This TIP proposes to remove all functions which use the _va\_list_ type from the public API, and it describes what extensions using this should do to make their extension portable on the mingw-w64 gcc compiler on the AMD64 platform. # Rationale The use of _va\_list_ in public API has the problem that different compilers have a different implementation of the _va\_list_ structure. The implication of this is that extensions which are compiled with mingw-w64 for the AMD64 platform, and call any of those functions will fail with a MSVC-compiled Tcl core. The reverse fails as well. For a brief description about this problem, see: <http://www.bailopan.net/blog/?p=30.> See also an earlier discusion in the Tcl Core mailing list: <http://code.activestate.com/lists/tcl-core/10807/> # Specification This TIP proposes to remove the following 4 functions from the public API * Tcl\_AppendResultVA * Tcl\_AppendStringsToObjVA * Tcl\_SetErrorCodeVA * Tcl\_PanicVA In addition, the inclusion of <stdarg.h> should move from tcl.h to tclInt.h, as no public Tcl header uses it any more. # Compatibility Extensions using any of those functions will not compile and run in Tcl 9.0 any more. They should be rewritten to use the same functions without the VA parameter. This can be done as follows. Before: int mypanic(const char *fmt, ...) { va_list ap; va_start(ap, fmt); Tcl_PanicVA(fmt, ap); va_end(ap); } After: int mypanic(const char *fmt, ...) { va_list ap; char *arg1, *arg2, *arg3, *arg4; va_start(ap, fmt); arg1 = va_arg(argList, char *); arg2 = va_arg(argList, char *); arg3 = va_arg(argList, char *); arg4 = va_arg(argList, char *); va_end(ap); Tcl_Panic(fmt, arg1, arg2, arg3, arg4); } The number of args used \(4, in this example\) should be chosen to be the maximum number of additional parameters that is used in any "mypanic" call. Since this function is only ever called from the extensions itself, this can be determined easily. In addition, the extension must do its own inclusion of <stdarg.h>, as tcl.h doesn't do that any more. Extensions rewritten this way, will continue to compile and function with Tcl 8.x as well. I am not aware of any extension which actually calls any of those VA functions. # Reference Implementation A reference implementation is available in the **novem-remove-va** branch. <https://core.tcl.tk/tcl/timeline?r=novem-remove-va> # Copyright This document has been placed in the public domain. |
Name change from tip/423.tip to tip/423.md.
|
| < | < | | | | | | | | > | | | | | | | | | | | > | 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 | # TIP 423: Formatting Timestamps with Milliseconds Author: Thomas Perschak <[email protected]> State: Draft Type: Project Tcl-Version: 8.7 Vote: Pending Created: 07-Jun-2013 Post-History: Keywords: Tcl, time, millisecond resolution ----- # Abstract This TIP describes a change to **clock format** to allow it to handle timestamps with sub-second accuracy. # Rationale Currently, the **clock format** accepts only integer numbers for clock formatting. Since the **clock milliseconds** command was introduced in Tcl 8.5, this limitation seems a bit restrictive. In particular, the timestamp column in a number of databases \(e.g., <http://www.postgresql.org/docs/9.1/static/datatype-datetime.html\)> handles high-resolution timestamps by allowing full ISO 8601 times, which look like "04:05:06.789"; this would simplify database write operations. # Proposal The **clock format** command should accept floating point values for timestamps. Another format letter should be added to **clock format** which puts the milliseconds into the output string; the millisecond value should not be written unless explicitly requested. # Copyright This document has been placed in the public domain. |
Name change from tip/424.tip to tip/424.md.
|
| < | < | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 424: Improving [exec] Author: Alexandre Ferrieux <[email protected]> State: Draft Type: Project Vote: Pending Created: 07-Jul-2013 Post-History: Keywords: Tcl,subprocess,execution Tcl-Version: 8.7 ----- # Abstract This extension overcomes day-1 limitations of [**exec**]'s syntax, allowing for unconstrained arguments to commands, and opening the path to more exotic redirections. # Summary Change Replace: exec foo bar baz > file With: exec | {foo bar baz} > file # Rationale For decades people have rightfully complained about the stubborn limitation of **exec** that prevents it from using commands or args resembling a redirection. It's not just Quoting Hell; it is simply impossible to spawn the equivalent of Bourne Shell's "echo \\>" from pure Tcl \(i.e., without resorting to another shell\). The reason \(excuse?\) for this is an unfortunate design choice: stick as closely as possible to the Bourne Shell's syntax, which indeed seamlessly intertwines commands, arguments, and redirects. This is unfortunate, because it overlooks a key difference between the two shells: * In Bourne Shell, since everything is about spawning commands, redirects are expected everywhere; hence their quoting is ubiquitous, and part of the language. * In Tcl, spawning processes is only a tiny part of the story. Consequently, redirect chars \(<>\|\) are not special, and deserve no core-language quoting rules. In this situation, it would have been possible to add an **exec**-specific layer of quoting, just for these characters. But as usual, the quoting char itself \(typically "**\\**"\) would have itself needed quoting \("**\\\\**"\), which would have overburdened the backslash density of all but the simplest pipelines... More importantly, the realization that this was Really Wrong came fairly late in Tcl's life; or at least late enough to consider any incompatible fix out of the question. So **exec** can be _extended_, not _fixed_. A few such extensions have been suggested over the years, but none reached critical mass. A possible interpretation of this is that they were considered too "disruptive" - while necessary only for a corner case. The current proposal addresses all the above concerns. Here are its design goals by decreasing importance: 1. Current **exec**'s unescapable warts should disappear > \(Yeah, take care of that corner case.\) 2. Current **exec**'s mapping to **open \|** should be carried over > \(This part of **exec**'s design was Good\) 3. Simple pipelines should give easy-to-read lines \(like current **exec**\) > \(No disruption, Ma'am\) 4. Shell-ish advanced redirections like "**3>&5**" should be supported > \(Not just the corner case: you get a free lunch too\) # Definition * Extend **exec** "from its error space", by reserving a single pipe character passed as its first argument: exec | ... ;# activates the new syntax open "|| ..." ;# same in [open] * Once the new syntax is unambiguously introduced, parse the rest as follows: exec | $cmd1 {*}$redirs1 | ... | $cmdN {*}$redirsN ?&? open "|[list | $cmd1 {*}$redirs1 | ... ]" > where: > \* **$cmd**_K_ and **$redirs**_K_ are lists > \* **$cmd**_K_ is a simple command-and-args, no extras > \* **$redirs**_K_ is a list of current exec redirection operators Examples: exec | {echo >} ;# this returns ">" exec | {cmd "<funny>xml</funny>"} 2>@ $ch < /dev/null | {cmd2 arg} >&2 Goals reached: 1. Unescapable warts are gone because the **$cmd** vs **$redir** status is positional, not content-based: each command-and args is a separate sublist, with no in-band encoding of redirections. 2. The above mapping is consistent with the existing **open \|[list foo bar]** logic. It respects the invariant saying, for **open \|**, that **[string range $openarg 1 end]** is always the list that would be passed, expanded, to **exec**. And it is handy to type **open "\|\| \{foo >\} > file"** 3. Simple pipelines are simple. > **exec \| $cmd1 \| $cmd2 \| $cmd3 > file** 4. Advanced redirections are imaginable since the redirection subsyntax now lives on its own. For example, with a putative "NUMBER>@" family of operators, one could define a nonlinear pipe graph: lassign [chan pipe] pr pw exec | {demuxer ...} 3>@ $pw | {filter ...} | {muxer ...} 3<@ $pr The definition of these advanced operators will be hosted by another TIP. # TL;DR This very conservative syntax, in addition to preserving the overall style and density of current **exec**, overcomes all the limitations and reaches Bourne Shell power. Moreover, it leverages the existing internals, so a nearly free side-effect is that it works with **pid** and **close** just like current **exec** does. # Rejected Alternatives * Replace the leading "**\|**" in **exec \|** by **--extended** * Use a different toplevel command name. > **exec2**... # Reference Implementation Branch "tip-improve-exec" on core.tcl.tk holds the implementation. # Copyright This document has been placed in the public domain. |
Name change from tip/425.tip to tip/425.md.
|
| < | < | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 425: Internationalization of Default Panic Callback on Windows Author: Jan Nijtmans <[email protected]> State: Draft Type: Project Vote: Pending Created: 17-Jul-2013 Post-History: Keywords: Tcl,platform integration,i18n Tcl-Version: 8.7 ----- # Abstract The default panic proc on Windows console applications writes the message in UTF-8 to stderr. Unfortunately, the Windows console normally does not have UTF-8 as code page but some single-byte code page like CP1252. When using characters outside the ASCII range, that does not give the expected output in the console. This TIP proposes to add a new Console panic proc to the stub library, and modify the Tcl\_Main\(\) macro to use it. # Rationale Many parts of Tcl are initernationalized in Tcl 8.6: The command line handling, and the communication with all Win32 API functions. But the Panic proc has - so far - not been modified accordingly for Windows console applications, even though win32 has a suitable API to do so. On Windows, there actually are two different panic procs, one for GUI applications and one for console applications, but external embedders don't have an API for deciding which one should be used other than provide their own. This TIP can finally do that: The call _Tcl\_SetPanicProc\(Tcl\_ConsolePanic\)_ will initialize the Tcl subsystem for Console applications, while _Tcl\_SetPanicProc\(NULL\)_ will continue to use the default. Making things worse, stderr is implemented by the C runtime, \(msvcrt??.dll\) but if a application is embedding or dynamically loading tcl.dll then the runtime of the embedder might be different from tcl.dll/tclsh.exe's runtime. The embedder providing the panic proc gives the highest chance that panic messages arrive in the same runtime as the embedder. For tclsh.exe this makes no difference. # Proposed Change A new function _Tcl\_ConsolePanic_ is added to the stub library on Windows and Cygwin, which can be installed by embedding application as panic proc. The full signature is: > EXTERN void **Tcl\_ConsolePanic**\( const char \*_format_ ...\); On other platforms than Windows or Cygwin, _Tcl\_ConsolePanic_ is a macro equivalent to NULL, on those platforms Tcl\_SetPanicProc\(Tcl\_ConsolePanic\) has the effect of resetting the panic proc to the platform's default. This function is meant to be used for Win32 or Cygwin console applications, and can deliver the message in 3 possible ways * If a \(Windows\) debugger is running, the message is sent there. * If stderr is connected to a Windows console, the message is sent there \(Windows only\). * Otherwise, the UTF-8 BOM \(3 bytes\) is written followed by the unmodified message \(assumed to be in UTF-8\). The function _Tcl\_ConsolePanic_ does not assume any locale, does not allocate memory, neither does it make any assumptions on the initialized state of Tcl. This makes Tcl\_Panic work fine even in the final stage of a Tcl\_Finalize\(\) call. If a Win32 Unicode API is available for the desired output, _Tcl\_ConsolePanic_ will do at most an UTF-8 to Unicode conversion using the Win32 function MultiByteToWideChar\(\). The maximum number of \(unicode\) characters that is written is 26000, as that is the maximum that WriteConsoleW\(\) can handle in a single call. See: <https://connect.microsoft.com/VisualStudio/feedback/details/635230> If the message is longer than that, the string is truncated and three dots appended to it. If the message is sent to a character device, the UTF-8 BOM is prepended. The function is available from the stub library, in order to bring the responsibility for correct linking to the embedding application, in stead of Tcl. In case of tclsh.exe, this makes no difference. # Reference Implementation A reference implementation is available in the **win-console-panic** branch. <https://core.tcl.tk/tcl/info/00a17823f0> # Copyright This document has been placed in the public domain. |
Name change from tip/426.tip to tip/426.md.
|
| < | | | | | | < | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 426: Determining the "Type" of Commands State: Draft Type: Project Tcl-Version: 8.7 Vote: Pending Post-History: Author: Donal K. Fellows <[email protected]> Created: 31-Jul-2013 Keywords: introspection, commands, Tcl, Tk ----- # Abstract This TIP describes a mechanism for determining what "type" of command a particular command is. This can be used as a prelude to performing other kinds of introspection, such as using **info body**, **namespace origin** or **interp alias**. # Rationale Currently, in order to find out information about an arbitrary command you have to apply a suitable introspection command and deal with any errors arising in order to tell that you had a command of some other type. It was made clear to me at EuroTcl 2013 that this was inelegant, especially since we in principle had the information available to do something neater. The information in question is the pointer to the implementation function, that's stored in the C record describing the command. All that is needed is a way to surface that information to Tcl as a new introspection command. # Proposed Change This new introspection interface shall consist of one new subcommand of **info** and a pair of new public C functions. > **info cmdtype** _commandName_ The new **info** subcommand is to be called **cmdtype** \(the name is chosen so as to not conflict with abbreviations **info commands** even though it does conflict with **info cmdcount**\) and it takes a single argument, _commandName_, which must be the name of an existing Tcl command. The result of this subcommand shall be a string describing what sort of command _commandName_ is; if no other information is available, the result shall be **native**. NB: The Tcl implementation will not make any guarantees of the command type for any particular command supplied by default in any interpreter. User code should never assume that just because a command is implemented one way in one particular version that it will continue to be implemented that way in any future version. ## Supporting C API The supporting public C functions shall be: > void **Tcl\_RegisterCommandTypeName**\(Tcl\_ObjCmdProc *_implementationProc_, const char \*_nameStr_\) > const char \* **Tcl\_GetCommandTypeName**\(Tcl\_Command _command_\) **Tcl\_RegisterCommandTypeName** will associate a particular implementation function, _implementationProc_, with an \(assumed literal constant\) string, _nameStr_; if _nameStr_ is supplied as NULL, the mapping for _implementationProc_ will be removed. The _implementationProc_ argument must not be NULL. The use of a package prefix within the name is _recommended_. **Tcl\_GetCommandTypeName** shall take a command handle, _command_, and return the registered type name string \(as previously passed to Tcl\_RegisterCommandTypeName\) for the command implementation function that the _command_ is using. If there is no type name registered for the command's implementation function, the literal string **native** will be returned instead. The result will never be NULL. ## Predefined Command Types The following command types are guaranteed to be among the set defined by default, but others may be done as well. proc: Procedures defined by the **proc** command. alias: Aliases defined by the **interp alias** command. ensemble: Ensembles defined by the **namespace ensemble** command. import: Commands imported by the **namespace import** command. object: Object \(or class\) defined by instantiating any TclOO class. ## Impact on Tk It is anticipated that Tk widget instances will report themselves through this mechanism as well, with a prefix to their names of **tk::**; that prefix _should not_ be used by any other package. Note however that not all widget types will be distinguishable; this is part of the way that Tk is implemented. The built-in widget creation functions _may_ declare themselves to be of type **tk::widgetFactory**. # Copyright This document has been placed in the public domain. |
Name change from tip/427.tip to tip/427.md.
|
| < | < | | | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 427: Introspection of Asynchronous Socket Connection Author: Reinhard Max <[email protected]> Author: Harald Oehlmann <[email protected]> Author: Reinhard Max <[email protected]> State: Final Type: Project Vote: Done Created: 16-Mar-2014 Post-History: Keywords: async socket connect,introspection,IPV6 Tcl-Version: 8.6.4 ----- # Abstract This TIP describes a method to introspect the asynchronous connection process by an extension of the **fconfigure** interface in addition to **fconfigure -error**. This will enable better control over the asynchronous connection process, even in cases where the event loop is not in use. # Rationale The **socket** core command supports two ways to establish a client socket, _synchronous_ and _asynchronous_. In synchronous mode \(which is the default\) the command does not return until the connection attempt has completed \(established or failed\). In asynchronous mode \(**-async option**\) the command returns after DNS lookup and the connection is established in the background. This is useful in situations where it is undesirable that a process or thread blocks for completing a synchronous connection attempt. Classically, an asyncronously connecting socket would indicate that it had connected \(or failed to connect\) by becoming writeable, which **fileevent writable** can be used to detect. A DNS name may have multiple IP addresses associated, e.g. for IPv4/IPv6 dual stack hosts or for fail safety or load balancing reasons as it is the case for google.com as of this writing. In Tcl 8.5 the socket command only tried to connect to a single IPv4 address that was randomly picked from the list returned by DNS. In Tcl 8.6, the socket command tries to connect to all the IP addresses of a DNS name in turn until one succeeds or all have failed. This caused the following changes to the **socket -async** command from Tcl 8.5 to 8.6: * The socket introspection options to **fconfigure** \(i.e., **-error**, **-sockname** and **-peername**\) can change between successive invocations while the connection is in progress as they reflect the state of the internal loop over the IP addresses. * The event loop must run in order to allow looping over the various possible IP addresses of a host. The usage of **socket -async** is seen as helpful even without the event loop. An example is an application, which checks a list of hosts for a connection. The application may start many background socket connects, do something else, and then collect the results. Without the event loop \(i.e., a **fileevent writable**\), there is no non-blocking way to discover if the asynchronous connect has completed. In addition, the following future points may be considered: * The connection process may internally get delegated to its own thread; this would allow the connection process to be asynchronous without requiring the event loop. * A future Windows implementation may use the Vista\+ API _WSAConnectByList_ \(once we do not support Windows XP any more\). Using this, no own looping over the addresses is necessary. It allows the connection process to be a single OS call, but does not allow inspection of the different connection steps. # Proposed Change ## Current Introspection Change The introspection functions should act as follows during an asynchronous connection process: * **fconfigure -error** will return the empty string \(no error\) * **fconfigure -sockname** will return the empty string * **fconfigure -peername** will return the empty string ## Introspection Command to Inspect a Running Asynchronous Connect An additional introspection function should inform if the asynchronous connect is running or if it has terminated: > **fconfigure** _channel_ **-connecting** This option returns **1** as long as a socket is still in the process of connecting asynchronously and 0 when the asynchronous connection has completed \(succeeded or failed\) or the socket was opened synchronously. ## Non-Event Loop Operation If the event loop runs, the state machine of a \(possibly multiple-address try\) async connection proceeds within an internal callback. In addition to that \(for the case the event loop does currently not run\), it proceeds whenever a channel operation is attempted on the socket\_ * nonblocking I/O and [fconfigure] will advance it by one step \(i.e. do whatever is doable without waiting\). * blocking I/O will advance it to completion, in essence meaning "switch back to synchronous connect, and in case of success, do the blocking I/O I asked for". # Use Case of the Connecting Option My own use case for the proposed option **-connecting** is as follows. A TCL script is started within Rivet to do two tasks: * Verify many URLs for existance \(e.g. open a socket and do a head request\). * Do some data base work. I don't use the event loop to get a linear program with controlled order. So the program flow is as follows: * Open async sockets for all links to verify: > _foreach host $hosts; set h\($host\) [socket -async $host 23]_ * Do some data base work which takes time. * Check all open sockets and eventually advance the state machine by calling **-connecting**: > _foreach host $hosts; if \{[fconfigure $h($host) -connecting]\} \{Connected $host\}_ * Do some more data base work which takes time. * Check **-connecting** and react until there are no open sockets any more. I have cut the data base processing into two parts; I assume there are normally two IP's to try, one IPV6 and one IPV4. # Alternatives Two alternatives for the behavior of **fconfigure -sockname** and **fconfigure -peername** are: * If there is only one destination IP address, return this before the connection is really established. This may also happen if the socket has processed its _bind\(\)_ system call in such a way that it knows it will not attempt another, and is currently processing its _connect\(\)_ to the remote host. * If an asynchronous connect is running, raise an error. These are open to discussion. # Implementation The fossil branch _tip-427_ contains an implementation of these extensions. # Copyright This document has been placed in the public domain. |
Name change from tip/428.tip to tip/428.md.
|
| < | < | | | | | | | | | > | | | | | | | | | < | > | | | | | | | | | | | | | | | | | | | | | | | | | | | < | > | | | | | > | 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 | # TIP 428: Produce Error Dictionary from 'fconfigure -error' Author: Harald Oehlmann <[email protected]> Author: Harald Oehlmann <[email protected]> State: Draft Type: Project Vote: Pending Created: 16-Mar-2014 Post-History: Keywords: socket,non-blocking,error reporting,option dictionary Tcl-Version: 8.7 ----- # Abstract This TIP proposes a new method which allows to return the error message and the error code of a background socket error \(as reported by **fconfigure -error**\), similar to the option dictionaries produced by catch and try and consumed by return. # Rationale The error message of a background channel error may be retrieved and cleared by **fconfigure** _channel_ **-error**, but there is no access to the error code. In addition, the error may not be handled in the TCL-like way using **catch** or **try** \(or just let fail the program\). Specially the new **try** syntax \(see example in the man page\) is well suited to handle socket errors. Example: try {set h [socket $host $port]}\ trap {POSIX ECONNREFUSED} {} { # handle not open port } Drivers mostly use POSIX errors to report issues where the error code is more portable than the error message \(AFAIK\). To handle an error by **try**, the error must be thrown. We are limited to an option to the command **fconfigure**, as this is implemented within the driver interface. Throwing the error would change the semantics of **fconfigure** and thus should not happen \(consensus on the core list\). Instead, the new **fconfigure** operation should return the error message and the error code. To finally throw the error, an utility function \(**chan throwerror $h**\) may be defined in TCL. This is not part of this TIP. # Proposed Change The option **fconfigure channel -error** should be extended to take an optional argument as follows: > **fconfigure** _channel_ **-error** _?errorDictVar?_ If the optional argument _errorDictVar_ is given, the following dict is written in the named variable of the caller environment: * if there is no error, it should be set to **-code 0** * if there is an error, it should be set to **-code 1 -errorcode ** _errorCode_ This is executed in addition to the standard action of **fconfigure** _channel_ **-error**. # Example Usage example with failing async connect: % set h [connect -async localhost 30001] d00000af % fileevent $h writable {set x 1} % vwait x % fconfigure $h -error errorDict connection refused % set errorDict -code 1 -errorcode {POSIX ECONNREFUSED {connection refused}} % close $h The following example demonstrates the implementation of **chan throwerror** eg to throw the error from the provided dict. proc throwerror {h} { set errorMessage [fconfigure $h -errorDict] return -options $errorDict $errorMessage } # Alternatives * Revision 1.11 of this TIP proposed to really throw the error. * Revision 1.21 of this TIP proposed a new option to return an error dict directly. # Implementation The tip is implemented in fossil branch **tip-428**. # Remarks The idea of this semantics and a feasability study is from Reinhard Max. # Copyright This document has been placed in the public domain. |
Name change from tip/429.tip to tip/429.md.
|
| < | < | | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 429: A 'string' Subcommand for Concatenation Author: Andreas Leitgeb <[email protected]> Author: Alexandre Ferrieux <[email protected]> State: Final Type: Project Vote: Done Created: 27-Jul-2014 Post-History: Keywords: Tcl,cat,scriptlet result Tcl-Version: 8.6.2 ----- # Abstract This TIP describes a new \(sub\)command **string cat** to concatenate an arbitrary number of strings. # Rationale Tcl has string concatenation built-in. But that is lacking in two specific cases: * one cannot directly concat a braced string with anything else * scriptlets such as used for **lmap** are expected to contain commands, the last one of which returns a value. To have the scriptlet return a concatenated string or even just a single string literal, one currently needs to misuse some corner-case of a non-trivial command, like **return -level 0 $x$y** or **string map \{\} "$x$y"** just to have the scriptlet produce the string as its result. # Proposal I propose a new subcommand **string cat**, that will take an arbitrary number of arguments \(i.e., 0 or more\), and concatenate them into a single string that becomes the result of the command. It would be equivalent to creating a **list** of the separate arguments and use **join** on that list with an empty string as second argument. Compiling that new command to bytecode should be trivial, as concatenation of strings is already compileable. The added value would be allowing braced string literals to be involved, and promoting the resulting stack-item to the result of the command/scriptlet. \(This simple compileability is also meant to be a main advantage over **join [list ...] ""**, where the contents of the intermediate list are either a single word or many words, or **lindex [list ...] 0** where the contents of the intermediate list are a single word.\) The following equality will hold for any arbitrary contents of the variables **a** and **b**: string equals $a$b [string cat $a $b] # Rejected Alternatives Lars has mailed on tclcore that TclX has a command **cconcat** that does essentially what my proposed **string cat** is supposed to do \(not sure though whether that is compiled\). This proposal sticks to the **cat** subcommand, as that is generally the preferred way over new toplevel commands. Also, **string concat** is added to this section, for it is a bit longer than **string cat**, and \(as Lars put it\) **string cat** is less likely to be misinterpreted as "concat, just moved into the string ensemble." # Reference implementation Available as branch tip-429 on core.tcl.tk. # Copyright This document has been placed in the public domain. |
Name change from tip/43.tip to tip/43.md.
|
| < | < | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 43: How to be a TIP Editor Author: Donal K. Fellows <[email protected]> State: Draft Type: Informative Vote: Pending Created: 07-Jul-2001 Post-History: ----- # Abstract This TIP describes some of the rules and guidelines that the TIP Editor uses when accepting TIPs for the first time. # Rules There are some things that are hard rules, which should be obeyed even if it means having to postpone acceptance of the TIP or rewrite it yourself. * _Every TIP _must_ be relevant to Tcl and/or Tk._ > It's probably better to suggest that changes that affect just a single extension should be dealt with through the processes for feature requests for that extension, but where they are about providing some kind common interface across a whole group of extensions, it is fair to think of using a TIP as well. I'd reckon that's up to the discretion of the editor, but no TIP should be rejected by the editor out of hand, and never without a proper written explanation. > Of course, ultimately whether a TIP is relevant to Tcl and/or Tk is up to the whole Tcl Core Team \(as described in [[0]](0.md)\) so you should try to ensure that their policy on TIP-suitability is what you are enforcing. * _Every TIP _must_ be in the TIP format \(see [[3]](3.md) for details.\)_ > This is important because it allows the TIP rendering engine to handle all the formatting and indexing automatically for you. Note that it is very picky about the format of the header, and not that choosy about the format of the content \(though it is not a good idea to have a sub-item of a list without a previous main item.\) Get it wrong, and the TIP archive engine will fail in all sorts of "interesting" ways. Take particular note of the format of the _Created:_ line, as it surprises many people in just how exact it must be. * _Every author _must_ be associated with a real email address._ > You should fill this in yourself if it is not already supplied and spam-protected addresses are not acceptable, since they tend to frustrate the main purpose of TIPs which is to foster collaboration on things to improve Tcl and Tk. Proper email addresses help this by always allowing people to contact the author of the TIP to give suggestions to improve the TIP or to resolve issues they have with it. * _Every TIP _must_ have an Abstract._ > Not everyone has the desire, or the time, to read each TIP. Providing an abstract allows people to determine whether the TIP is relevant to what they are looking for at the moment. Searches on the TIP archive also always search the abstract. > Abstracts should be formed of the section title whose text is precisely "Abstract" and then a single normal paragraph of no more than around 200 words; if it is longer than that then it is no longer a summary or abstract but a genuine major part of the document body. While authors should write their own abstracts, it is reasonable for the editor to add one, particularly if the author's native language is not English. * _Every TIP _must_ have a Copyright declaration._ > World-wide copyright laws are funny things, and I'm not sure that it is safe to assume that the submission of the TIP constitutes permission for all the things that might be done with it in the future. Work around this by getting every author to clarify the copyright position at time of submission by explicitly saying that the document is placed in the public domain. \(The way that TIPs are kept under CVS should assuage most concerns relating to misrepresentation through inappropriate modifications, and it is a definite aim that TIPs should be distributed as widely as possible to encourage a wide dissemination of the ideas contained.\) # Guidelines * TIPs should be written in English \(unless there are very good reasons otherwise\) since that is the language most widely understood in the Tcl/Tk community. * TIP should be written so as to be readable! This requirement is not strict, but it will make it much easier for the TCT to evaluate... * The Abstract should be written in a third-person voice, and _definitely_ in English. It isn't so important for the rest of the TIP, but the abstract will be seen quite a bit more widely and without as much context. It also fits in with the style of the existing abstracts. * The section headings and title should be capitalised according to the rules for such things in English. It looks neater that way. * Spell check before checking in. No sense in having glaring errors in the initial version! \(I do not enforce the use of either US or UK spellings; that is rightfully the domain of the TIP author who might be based anywhere in the world.\) Be especially careful with the checking of the spellings of the names of file names, C identifiers or Tcl commands/variables/etc. * C identifiers and Tcl commands/variables/etc. should normally be _emphasized_, as should file names. This should be moderated by good sense though; the aim of such emphasis is to indicate that it is a reference to an entity in the code domain as opposed to the domain of the English language. * TIP numbers should be allocated by the TIP editor in sequence of the order they are checked into the CVS archive. Make sure that the filename \(_num.tip_\) matches up with the _TIP: num_ header or bizarre things may happen. * Where someone submits a TIP proposing a new Tk widget, invite them to supply an image \(or two\) of how the widget will look in operation. These images will need to be checked in by hand, and will not be editable. Images should be checked in in both a raster form \(GIF, JPEG or PNG\) and as Encapsulated PostScript \(EPS\) - make sure that you set the binary flag on the file when you do this. Where someone produces a diagram with a tool that can produce FIG files, it is nice if you can check that into CVS as well so that the diagram itself can be maintained if necessary. > As a convention, name the images with the TIP number as the first part of the name. This makes it much easier to determine what TIP a particular image is associated with \(and certainly beats grepping the whole set of TIPs!\) * Once a TIP is checked in, it should normally be published to news:comp.lang.tcl, news:comp.lang.tcl.annouce and the tcl-core mailing list \(though with some TIPs it is obvious that wider dissemination is less useful.\) It is a good idea to send a copy to the TIP author as well, as this lets them know not only that the TIP has been accepted but also what it looks like and that it has been distributed to the wider community. The _postnews.tcl_ script that comes with the TIP renderer distribution is designed to do all this with a minimum of fuss. A quick "Thank You" note is also courteous. * When a TIP has been accepted by the TCT in a TYANNOTT vote, put a note into the log to record what the vote was. It is best to do this as part of the log message for when you change the Vote: and Status: headers... * If a TIP does not state whether it is an alteration to Tcl or Tk in either its title or its abstract, it is a good idea to add a Keywords: header \(or a keyword in an existing such header\) which includes that information. * Don't forget to use both **bold** and _italic_ text when formatting strings that represent command syntaxes. It makes them much clearer! _I need to write something here about the production of PS and PDF versions of the whole TIP archive, but that side of the code is not yet finished and released._ # Notes TIPs do not need to be tightly focussed. Making them so does make them easier to evaluate, but it might also remove the real rationale behind the changes. Instead, it is best that they form a coherent logical entity, since I believe that it is that which makes for a good TIP. The title, section headings and list item headings must be plain text. This is because there are output formats which are very picky about what is allowed in those sorts of places \(PDF bookmarks have especially strict restrictions\) and plain text has the virtue of being accepted pretty much everywhere. # Copyright This document is placed in the public domain. |
Name change from tip/430.tip to tip/430.md.
|
| < | < | | | | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 430: Add basic ZIP archive support to Tcl Author: Sean Woods <[email protected]> Author: Donal Fellows <[email protected]> Author: Poor Yorick <[email protected]> Author: Harald Oehlmann <[email protected]> State: Draft Type: Project Vote: Pending Created: 03-Sep-2014 Post-History: Keywords: virtual filesystem,zip,tclkit,boot,bootstrap Tcl-Version: 8.6.3 ----- # Abstract This proposal will add basic support for mounting zip archive files as virtual filesystems to the Tcl core. # Target Tcl-Version This TIP targets TCL Version 8.7 or 9.0, whatever comes first. # Rationale Tcl/Tk relies on the presence of a file system containing Tcl scripts for bootstrapping the interpreter. When dealing with code packed in a self-contained executable, a chicken-and-egg problem arises when developers try to provide this bootstrap from their attached VFS with extensions like TclVfs. TclVfs runs in the Tcl interpreter. The interpreter needs _init.tcl_, which would mean that the filesystem containing _init.tcl_ is not present until after TclVfs mounts it yet that mount cannot happen until after _init.tcl_ has been loaded. Bootstrap filesystem mounts require built-in support for the filesystem that they use. With the inclusion of Zlib in the core \(starting with 8.6, [[244]](244.md)\), all that is required to implement a zip file system based VFS is to add a C-level VFS implementation to decode the zip archive format. Thus: this project. Note that we are prioritizing the zip archive format also because it is practical to generate the files without a Tcl installation being present; it is a format with widespread OS support. This makes it much easier to bootstrap a build of Tcl that uses it without requiring a native build of tclsh to be present. # Specification There shall be new commands added to safe interpreters withing Tcl. All of which shall be in the **::zvfs** namespace. These commands shall include: * **zvfs::mount** ?_archive_? ?_mountpoint_? > Mounts the ZIP file _archive_ at the location given by _mountpoint_, which will default to **zipfs:_/_archive_ if absent. With no arguments this command describes all current mounts, returning a list of pairs. * **zvfs::unmount** _archive_ > Unmounts the ZIP file _archive_, which must have been previously mounted. Safe interpreters will not be given the mount or unmount commands. Already mounted file systems will be available via the **glob** and **file** commands. These commands, and any commands related to building archives will be marked with the unsafe bit within the **zipfs** ensemble, and will be removed from any interpreter through the normal mechanism to hide unsafe commands within the core. # Implementation I have adapted Richard Hipp's work on Tcl As One Big Executable \(TOBE\) to operate inside of a modern Tcl. That implementation consists of one C file \(_tclZipvfs.c_\). I have also prepared new behaviors for inside of Tcl\_AppInit\(\) to detect if a zip filesystem is attached to the current executable, and how to extract a "_main.tcl_" as well as the initial file systems for both Tcl and Tk. This work is checked in as the "_core\_zip\_vfs_" branch on both Tcl and Tk. # C API * **int TclZipfsInit\(Tcl\_Interp \*interp\);** > Initializes the C API for Zipfs. If called with a non-null _interp_, adds the commands for the zipfs Tcl API to the interpreter. Returns **TCL\_OK** on success, and **TCL\_ERROR** in all other cases. * **int TclZipfsMount\(Tcl\_Interp \*interp, const char \*zipname, const char \*mntpt, const char \*passwd\);** > Mounts a zip file _zipname_ to the mount point _mntpt_. If _passwd_ is non-null, that string is utilized as the password to decrypt the contents. _mnpnt_ will always be relative to **zipfs:** * **int TclZipfsUnmount\(Tcl\_Interp \*interp, const char \*zipname\);** > Unmount the file system created by a prior call to **TclZipfsMount\(\)** # Bootstraping The mount and unmount commands are usable within the core as just another feature engine. A call to TclZipfsInit\(\) will be inserted into tclBasic.c, immediately after the code to initialize zlib. A modified shell \(tclkit.exe\) will be generated by Make. This shell will: * Check if the executable has a zip archive attached. If so, that archive shall be mounted as **zipfs:/app**. * If _zipfs:/app" is present the interpreter will look for **boot/tcl/init.tcl**. If that file is present, the location for **$tcl\_library** will be set to **zipfs:/app/boot/tcl**. * If _zipfs:/app_ is present the interpreter will look for **boot/tk/tk.tcl'. If present the location for **$tk\_library** will be set to **zipfs:/boot/tk**. * If the file **pkgIndex.tcl** is present, the **$dir** variable will be set to **zipfs:/app** and the file will be sourced as if it were a package index. * If the file **main.tcl** is present, the file **zipfs://app/main.tcl** will be registered with **Tcl\_SetStartupScript\(\)** # Copyright This document has been placed in the public domain. |
Name change from tip/431.tip to tip/431.md.
|
| < | < | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 431: Add 'tempdir' Subcommand to 'file' Author: Kevin Pasko <[email protected]> State: Draft Type: Project Tcl-Version: 8.6.4 Vote: Pending Created: 10-Sep-2014 Keywords: Tcl, directory, file Post-History: ----- # Abstract This TIP proposes adding a new **tempdir** subcommand to the **file** command, simplifying the effort required in creating uniquely named temporary directories at the scripting level. # Rationale Due to the non-atomic nature of the **file mkdir** command it is currently impossible to create uniquely named temporary directories at the script level without the possibility of race conditions. # Specification The **file tempdir** command shall implement the functionality of the POSIX standard mkdtemp\(\) function. With no arguments **file tempdir** shall create a uniquely named temporary directory in the native operating system's temporary directory, with naming convention "**tcl\_**_XXXXXX_" where each _X_ is a randomly selected character \(following the **file tempfile** naming convention\). Successful completion of **file tempdir** shall return the absolute path of the created directory, otherwise an error shall be thrown. **file tempdir** shall have an optional argument, _template_, to modify the created directory's path and name. The _template_ shall be decomposed into \(up to\) two parts: the directory's path and rootname. If either part is absent, relevant defaults \(e.g., according to the native operating system\) shall be used. The entire temporary name shall then be formed from the path, the root, and a generated unique string of \(typically\) six characters. The command syntax should be defined as: > **file tempdir** ?_template_? # Considerations * The subcommand **tempdir** could be a candidate, later, for returning the native file system's temporary directory. Naming the subcommand something else such as **mktempdir** is another option, though strays from the **file tempfile** naming convention. * For future extensibility the **template** argument to **file tempdir** \(since it is optional\) could be specified in the key / value format, **-template**, changing the command syntax to: > > **file tempdir** ?_options..._? # Reference Implementation An example of temporary directory creation has already been developed into the Tcl core, at the C level, within the platform specific layers of the **load** command. The principal work remaining is to expose this via a Tcl command. # Copyright This document has been placed in the public domain. |
Name change from tip/432.tip to tip/432.md.
|
| < | < | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 432: Support for New Windows File Dialogs in Vista and Later Author: Ashok P. Nadkarni <[email protected]> State: Final Type: Project Vote: Done Created: 20-Sep-2014 Post-History: Tcl-Version: 8.6.3 ----- # Abstract This TIP proposes changing the **tk\_getOpenFile**, **tk\_getSaveFile** and **tk\_chooseDirectory** dialog box commands to display the new style file dialogs available on newer Windows versions. # Rationale As of Tk 8.6.2, the above commands translate to Windows native file dialogs corresponding to the ones present in Windows XP \(the earliest version of Windows supported by Tcl 8.6\). Vista and later Windows systems have newer versions of these dialogs with additional features and a different look and feel. Although the older dialogs are functional on these platforms, they have the following issues: * They do not support the new features, such as breadcrumbs, enhanced navigation etc. * The look and feel is dated and inconsistent not only with other native applications, but even with Tk itself since the Ttk widgets adapt to the theme for the platform. In addition, this TIP proposes some changes to behaviour with respect to existing dialogs that would make the dialogs more consistent with Windows conventions. # Proposed Changes The proposal will result in the **tk\_getOpenFile**, **tk\_getSaveFile** and **tk\_chooseDirectory** dialog box commands displaying the new Vista style file dialogs if available and falling back to the older style otherwise. Options to the commands and return value from the dialogs remain unchanged except as noted below. ## Incompatible changes If the **-initialdir** option is not specified, the new dialog will default to the default Windows mechanism for choosing the initial directory displayed. Documentation will be updated to state that the initial directory displayed when this option is not present is system dependent. # Reference Implementation A reference implementation is available in the apn-win-filedialogs branch. The new dialogs require a new COM interface IFileDialog. The reference implementation uses this interface if available and falls back to the old one otherwise. # Discussion * The change in behaviour when **-initialdir** is not specified is driven by the fact that on Windows the current working directory for a GUI program is generally the directory where the program was installed. This is almost never useful and is contrary to what the user expects which is the last directory shown by the program \(even across process invocations\). * Should there be either a global setting or an option that forces the use of old style dialogs. Alternatively, should the new dialogs be only displayed if a \(new\) option is specified with the command. The author is not in favor of either of these but applications that have documented screenshots may wish to preserve the old dialogs. As of now, the reference implementation has a hidden option **-xpstyle** that can be used to select between old and new styles. This is present mainly to allow debugging and testing of the older dialogs on newer platforms. * The new implementation calls **CoInitialize** to initialize COM. It is not clear when, and if, **CoUnInitialize** needs to be called. In fact, as documented in MSDN, even the **SHBrowseForFolder** call used by the current 8.6 code requires a prior call to **CoInitialize** which Tcl does not do. Need discussion on whether Tcl should always call **CoInitialize** at thread startup and **CoUnInitialize** at thread shutdown. # Copyright This document has been placed in the public domain. |
Name change from tip/433.tip to tip/433.md.
|
| < | < | | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | < < | > > | | | | | | | | | | < < | > > | | | | | | | | | > | 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 | # TIP 433: Add %M binding substitution Author: Joe Mistachkin <[email protected]> Author: Brian Griffin <[email protected]> Author: Don Porter <[email protected]> State: Final Type: Project Vote: Done Created: 25-Feb-2015 Post-History: Tcl-Version: 8.6.4 ----- # Abstract This TIP proposes one new binding substitution, **%M**, to access the number of script-based binding patterns matched so far for the event. # Background In a presentation at the 2012 Tcl Conference \(<http://www.tclcommunityassociation.org/wub/proceedings/Proceedings-2012/RonWold/Customizable-Keyboard-Shortcuts.pdf\),> Ron Wold pointed out that coding global catch-all scripts bound to the same event in many widgets is complicated because Tk's **bind** machinery allows any bind script to use **break** to prevent later bind scripts from evaluating. Among a known set of bind scripts, this is a useful technique, but it interferes with the non-coordinated introduction of additional bind scripts on the same event. An alternative strategy is to avoid any bind script using **break**, but to give the latter scripts the means to detect when an earlier script has run so it can defer its own operations. That motivates the introduction of a means by which a bind script can discover something about the history of other bind script evaluations on the same event. # Specification Add to the set of substitutions made in scripts passed to **bind** the new one, **%M**. When the substring **%M** appears in a binding script, it will be replaced with a count of the number of binding script evaluations that have already been performed in the handling of the current event. # Simple Example The script... pack [entry .e] bind all <Key> {set z %M} bind Entry <Key> {set y %M} bind .e <Key> {set x %M} event generate .e <Key-a> list $x $y $z will produce the result: 0 1 2 # Use Case Example One of the default bind scripts in Tk is event add <<NextWindow>> <Tab> bind all <<NextWindow>> {tk::TabToWindow [tk_focusNext %W]} which permits a **<Tab>** anywhere in Tk to shift the focus. Some widgets have their own uses for **<Tab>**, though, notably bind Text <Tab> { if {[%W cget -state] eq "normal"} { tk::TextInsert %W \t focus %W break } } where a text widget in normal state accepts **Tab**s as entered text like any other keypresses. The **break** in this script serves to prevent the focus shift that would otherwise take place. Since the same Tk developers coded both bind scripts, the global knowledge can make the system work as a whole. However, a third party facility trying to join the party has difficulty. Consider a simple key logging facility, bind all <Key> {log_key %W %k %s %x %y %X %Y %A} This will fail to log **Tab**s typed in a Text due to the **break** noted above. With the **%M** binding proposed here, an alternative set of bind scripts is possible. bind all <<NextWindow>> {if {%M==0} {tk::TabToWindow [tk_focusNext %W]}} bind Text <Tab> { if {[%W cget -state] eq "normal"} { tk::TextInsert %W \t focus %W } } In fact with the revised script bound to **all** it may be that the script bound to **<Tab>** is no longer needed at all and the general default binding bind Text <KeyPress> {tk::TextInsert %W %A} is sufficient. With this alternative in place the third-party keylogger would work. # Compatibility Any **%M** in an existing bind script will now stop reproducing itself literally, and will result in the new substitution. This has the potential to cause trouble with any bind scripts that themselves make use of **clock scan** or **clock format** or any other command that invites the use of the literal string **%M**. Dealing with such a situation is not difficult, but it is still a potential incompatibility. # Prototype This feature is already implemented and committed to both the core-8-5-branch and the trunk, and is poised to be released as part of Tk 8.5.18 and Tk 8.6.4. Any objections to that should be raised in TIP discussion and voting. # Copyright This document has been placed in the public domain. |
Name change from tip/434.tip to tip/434.md.
|
| < | < | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 434: Specify Event Sources for 'vwait' Author: Jos Decoster <[email protected]> State: Draft Type: Project Tcl-Version: 8.6 Vote: Pending Created: 26-Feb-2015 Post-History: ----- # Abstract This TIP proposes to extend the **vwait** Tcl command so the event sources can be specified, as is possible with the **Tcl\_DoOneEvent** C command. # Rationale In some situations it can be required not to wait for specific event sources or to wait for specific events sources only. You might want the program to only react on timer events, and not on file or window events. You can write your own version of the **Tcl\_VwaitObjCmd** command in C, and call **Tcl\_DoOneEvent** with the flags you need. Making it possible to specify the event sources, i.e. the arguments for the call to **Tcl\_DoOneEvent** within **Tcl\_VwaitObjCmd**, from the Tcl **vwait** command would make this functionality available from the Tcl lebvel. # Specification This document proposes to add optional arguments to the **vwait** command. If these arguments are not specified, the current event source **TCL\_ALL\_EVENTS** will be used. If the optinal arguments are specified, they are the event sources to be passed to **Tcl\_DoOneEvent** within **Tcl\_VwaitObjCmd**. The flags set with the optinal arguments will be or-ed. Possible flags are corresponding to the flags for the **Tcl\_DoOneEvent** command: * **-all** \(default\) - process all events * **-file** - process file events * **-idle** - process idle events * **-timer** - process timer events * **-window** - process window system events Example: wait until variable **a** is written and only allow timer events to be processed: vwait a -timer # Alternatives A possible alternative is to add support for a **-events <event\_list>** argument. A **-dont\_wait** argument is not added, a call to **update** will have the same effect. # Compatibility No incompatibilities are introduced. # Reference Implementation A reference implementation is available. # Copyright This document has been placed in the public domain. |
Name change from tip/435.tip to tip/435.md.
|
| < | < | | | | | | | | > | | | | | | | | | | | | | | > | 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 | # TIP 435: Safe Mutex Disposal API Author: Donal Fellows <[email protected]> Author: Joe Mistachkin <[email protected]> State: Rejected Type: Project Tcl-Version: 8.6.5 Vote: Done Created: 16-May-2015 Post-History: ----- # Abstract This TIP proposes a new C API for improving mutex deletion. # Rationale Context: Bug \#57945b574a There is a race condition in the code that disposes of mutexes, in that a mutex must only be disposed of when it is not in use by another thread, yet the disposal code does not lock it. This would not be a particular problem as there is a _global_ lock that protects the disposal code, except that during the cleanup immediately after a fork \(during the **exec** command, for example\) things can get deeply confused, and trigger deadlocks under heavy load. We need to be careful and make sure that we really hold the global lock when unlocking and disposing mutexes. Because the pipeline-opening code isn't the only thing that might ever fork internally, we should provide the capability to do this correctly as part of Tcl's public API. # Specification This TIP specifies a single new function: > void **Tcl\_MutexUnlockAndFinalize**\(Tcl\_Mutex \*_mutex_\); The **Tcl\_MutexUnlockAndFinalize** function \(which takes a single argument, the mutex to operate on\) will atomically unlock the mutex and dispose of it without giving an opportunity for another thread to lock the mutex between unlocking and disposal. The mutex must have previously been locked by **Tcl\_MutexLock**. # Implementation See branch bug-57945b574a. # Acknowlegement Thanks to Gustaf Neumann for his trouble tracking this down, and apologies for the problems the fault has caused him. # Copyright This document has been placed in the public domain. |
Name change from tip/436.tip to tip/436.md.
|
| < | | | | | | < | | > | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 436: Improve TclOO isa Introspection State: Final Type: Project Tcl-Version: 8.6.5 Vote: Done Post-History: Author: Donal Fellows <[email protected]> Created: 30-Jun-2015 ----- # Abstract The various **info object isa** introspectors should not produce errors when given a non-object; the set membership tests should simply return boolean false in those cases. # Rationale The **info object isa** command is intended to be used to allow asking whether some object is a member of a general set of entities; for example, **info object isa object** allows querying whether you actually have a handle to an object at all. However, the other membership sets all throw an error when given a non-object. This complicates the use of the API when all that is really needed is to return a **false** value in those cases. Motivating example \(with thanks to Will Duquette\): is the **proc** a class? No. It's not even an object, so it clearly cannot be a class and so the following command should produce false \(or 0\) and not an error: info object isa class proc # Proposed Change Where one of the **info object isa** introspectors: * **info object isa** _class object_ * **info object isa metaclass** _object_ * **info object isa mixin** _object class_ * **info object isa object** _object_ * **info object isa typeof** _object class_ Would produce an error due to either the _object_ or \(where appropriate\) the _class_ object not passing some critical precondition to the test, the result of the command will be **0** \(i.e., boolean false\). Errors will be still generated when the wrong number of arguments are supplied. Note that this rule is already followed by **info object isa object**. # Copyright This document has been placed in the public domain. |
Name change from tip/437.tip to tip/437.md.
|
| < | | | | | | < | | | | > | | | | | | | | | | | | | | > | 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 | # TIP 437: Tk panedwindow options for proxy window State: Final Type: Project Tcl-Version: 8.5.18 Vote: Done Post-History: Author: Eric Boudaillier <[email protected]> Author: François Vogel <[email protected]> Created: 14-Jul-2015 Keywords: Tk ----- # Abstract The proxy window \(i.e., the moving sash\) of the Tk paned window widget is hard to see in some circumstances. This TIP adds three options allowing more control over the display of the proxy so that its visibility can be enhanced where required. # Rationale As identified in [Bug: 1247115, <https://core.tcl.tk/tk/tktview/1247115],> a flat sashrelief is common for **panedwindow** widgets, when it separates two widgets with sunken relief. For example, the left part can be a tree and the right part a text widget, both with a white background. Under Windows, the paned window has a light grey color, and in this configuration, the proxy window is not well visible when it is moved over its managed widgets. # Proposed Change It is proposed to add three options to the Tk **panedwindow** widget: **-proxybackground**, **-proxyrelief** and **-proxyborderwidth**. * **-proxybackground** controls the background of the proxy window. If empty \(the default\), the background is that of the panedwindow widget, which is the current behaviour. * **-proxyrelief** controls the relief of the proxy window. If empty \(the default\), the relief is that of the panedwindow widget, which is the current behaviour. * **-proxyborderwidth** controls the border width of the proxy window. The default value is 2, which is the current value. # Copyright This document has been placed in the public domain. |
Name change from tip/438.tip to tip/438.md.
|
| < | < | | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | < > | | | | | | | | | | | | | < > | | | | | | | | | | | | | | < < > > | | | | | | < | > | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 438: Ensure Line Metrics are Up-to-Date Author: François Vogel <[email protected]> Author: Jan Nijtmans <[email protected]> State: Final Type: Project Vote: Done Created: 01-Nov-2015 Post-History: Keywords: Tk,text Tcl-Version: 8.6.5 ----- # Abstract The text widget calculates line metrics asynchronously, for performance reasons. Because of this, some commands of the text widget may return wrong results if the asynchronous calculations are not over. This TIP is about providing the user with ways to ensure that line metrics are up-to-date. # Rationale The text widget features asynchronous calculation of the display height of logical lines. The reasons for this and the details of the implementation are explained at the beginning of tkTextDisp.c. This approach has definite advantages among which responsivity of the text widget is important. Yet, there are drawbacks in the fact the calculation is asynchronous. Some commands of the text widget may return wrong results if the asynchronous calculations are not finished at the time these commands are called. For example this is the case of **.text count -ypixels**, which was solved by adding a modifier **-update** allowing the user to be sure any possible out of date line height information is recalculated. It appears that aside of **.text count -ypixels** there are several other cases where wrong results can be produced by text widget commands. These cases are illustrated in several bug reports: * <http://core.tcl.tk/tk/tktview/1566949> \(.text yview moveto\) * <http://core.tcl.tk/tk/tktview/e51941c> \(.text yview\) In all these cases, forcing the update by calling **.text count -update -ypixels 1.0 end** before calling **.text yview**, or **.text yview moveto** solves the issue presented in the ticket. This has however a performance cost, of course, but the above tickets show that there are cases where the programmer needs accurate results, be it at the cost of the time needed to get the line heights calculations up-to-date. This TIP is about providing the user/programmer with \(better\) ways to ensure that line metrics are up-to-date. Indeed it is not appropriate to let the concerned commands always force update of the line metrics or wait for the end of the update calculation each time they are called: performance impact would be way too large. Also, it has to be noted that the **update** command is of no help here since the line metrics calculation is done within the event loop in a chained sequence of [after 1] handlers. # Proposed Change It is proposed to add two new commands to the text widget: > _pathName_ **sync** _?-command command?_ > _pathName_ **pendingsync** Also a new virtual event **<<WidgetViewSync>>** will be added. Description: _pathName_ **sync** Immediately brings the line metrics up-to-date by forcing computation of any outdated line pixel heights. Indeed, to maintain a responsive user-experience, the text widget caches line heights and re-calculates them in the background. The command returns immediately if there is no such outdated line heights, otherwise it returns only at the end of the computation. The command returns an empty string. Implementation details: The command executes: TkTextUpdateLineMetrics(textPtr, 1, TkBTreeNumLines(textPtr->sharedTextPtr->tree, textPtr), -1); _pathName_ **sync** **-command** _command_ Schedule _command_ to be executed exactly once as soon as all line calculations are up-to-date. If there are no pending line metrics calculations, the scheduling is immediate. The command returns the empty string. **bgerror** is called on _command_ failure. _pathName_ **pendingsync** Returns 1 if the line calculations are not up-to-date, 0 otherwise. **<<WidgetViewSync>>** A widget can have a period of time during which the internal data model is not in sync with the view. The **sync** method forces the view to be in sync with the data. The **<<WidgetViewSync>>** virtual event fires when the internal data model starts to be out of sync with the widget view, and also when it becomes again in sync with the widget view. For the text widget, it fires when line metrics become outdated, and when they are up-to-date again. Note that this means it fires in particular when _pathName_ **sync** returns \(if there was pending updates\). The detail field \(%d substitution\) is either true \(when the widget is in sync\) or false \(when it is not\). All **sync**, **pendingsync** and **<<WidgetViewSync>>** apply to each text widget independently of its peers. The names **sync**, **pendingsync** and **<<WidgetViewSync>>** are chosen because of the potential for generalization to other widgets they have. The text widget documentation will be augmented by a short section describing the asynchronous update of line metrics, the reasons for that background update, the drawbacks regarding possibly wrong results in **.text yview** or **.text yview moveto**, and the way to solve these issues by using the new commands. Example code as below will be provided in the documentation, since this code will not be included in the library \(i.e. in _text.tcl_\)\). The existing **-update** modifier switch of **.text count** will become obsolete. It will be declared as deprecated in the text widget documentation page while being still supported for backwards compatibility reasons. Using the new commands, ways to ensure accurate results in **.text yview**, or **.text yview moveto** are as in the following example: ## Example 1: # runtime, immediately complete line metrics at any cost (GUI unresponsive) $w sync $w yview moveto $fraction ## Example 2: # runtime, synchronously wait for up-to-date line metrics (GUI responsive) $w sync -command [list $w yview moveto $fraction] ## Example 3: # init set yud($w) 0 proc updateaction w { set ::yud($w) 1 # any other update action here... } # runtime, synchronously wait for up-to-date line metrics (GUI responsive) $w sync -command [list updateaction $w] vwait yud($w) $w yview moveto $fraction ## Example 4: # init set todo($w) {} proc updateaction w { foreach cmd $::todo($w) {uplevel #0 $cmd} set todo($w) {} } # runtime lappend todo($w) [list $w yview moveto $fraction] $w sync -command [list updateaction $w] ## Example 5: # init set todo($w) {} bind $w <<WidgetViewSync>> { if {%d} { foreach cmd $todo(%W) {eval $cmd} set todo(%W) {} } } # runtime if {![$w pendingsync]} { $w yview moveto $fraction } else { lappend todo($w) [list $w yview moveto $fraction] } # Rejected alternatives * Use a script-visible array variable such as **::tk::metricsDone\($w\)** instead of an event. * Don't change the source code and better document the **.text count -update -ypixels** trick. This is believed to be suboptimal considering that **.text count** indeed performs counting \(which has a cost\). This performance drawback could however be very much alleviated by counting between the two same indices: there would be no cost at all if this case was detected and was a short-cut in function TextWidgetObjCmd. * Instead of a new text widget sub-command, follow the lines of the existing example of **text count** and provide a new modifier switch **-update** to all sub-commands that may need it. The list of such sub-commands include **text yview**, **text yview moveto**, and **text yview scroll**. * **update idletasks** could force line metrics calculation update \(in addition to what this command already does\). This is certainly not the right thing to do since it is not very flexible. It would impact the performance of all text widgets whereas perhaps only one of them needs up-to-date line heights. Also, one could want to update idletasks \(in the current sense: idle tasks\) but not the line heights calculation, or the opposite. All in all, linking the event loop and the line heights calculation seems bad. * For each sub-command that needs up-to-date line heights to provide fully correct results, detect whether it is the case or not at the time they are called. If so, fine. If not, there could be two ways forward: > 1. Force the update. This is not believed to be desirable, again for performance reasons. While there are cases where accurate results are mandatory \(see the tickets above\), most of the time one can live with approximate results. Any mismatch is temporary, since the asynchronous line height calculations will always catch up eventually. It is preferred to let the programmer decide if this update is needed or not. > 2. Decide that the line height of not yet up-to-date lines is equal to some reasonable value, for instance the height of the first displayed line \(which is likely up-to-date\). For text widgets using only a single font, this would be OK since all line heights are then the same. However this would not solve all cases, for instance in **text yview** where the total number of pixels used by the text widget contents is needed, because this total pixel height calculation involves the total number of display \(not logical\) lines. Assessing the total number of display lines has a performance cost similar to proper line heights calculation, which voids that path. * It has been proposed that the detail field %d for the **<<WidgetViewSync>>** event contain the number of outdated lines, while this event would fire at each [after 1] partial update of the line metrics. This was rejected since no use case of this value could be exhibited, and it was believed that firing the event twice \(when out of sync and when again in sync\) was sufficient. * It has been proposed that the **text pendingsync** command return the number of currently outdated lines. This was rejected because no use case could be found, and because this TIP aims at generalization and it might be hard to define the equivalent of "number of lines to do" for other widgets. Anyway, using a boolean now \(noted as "1" and "0", rather than "true" and "false"\) leaves room to change our minds later with minimal incompatibility, since [if {[.t pendingsync]\}] will keep its semantics with an integer. # Copyright This document has been placed in the public domain. |
Name change from tip/439.tip to tip/439.md.
|
| < | < | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 439: Semantic Versioning Author: Jan Nijtmans <[email protected]> State: Draft Type: Project Vote: Pending Created: 08-Dec-2015 Post-History: Tcl-Version: 8.7 ----- # Abstract The version schema used by Tcl and Tk has the form MAJOR.MINOR.PATCH, which is the same schema used by "Semantic Versioning" <http://semver.org/> . For alpha and beta releases the schema is MAJOR.MINORaPATCH resp MAJOR.MINORbPATCH, which is not following the "Semantic Versioning" rules, but it's close. This TIP proposes to start using "Semantic Versioning" for Tcl and Tk, starting with Tcl/Tk 8.7, without making it mandatory for extensions and Tcl modules: existing extensions and modules written for Tcl/Tk 8.6 or lower must cooperate unmodified with later 8.x versions as well. # Rationale Semantic Versioning is an attempt to assign meaning to a software version number. It has a very simple rule: * Given a version number MAJOR.MINOR.PATCH, increment the: > \* MAJOR version when you make incompatible API changes, > \* MINOR version when you add functionality in a backwards-compatible manner, and > \* PATCH version when you make backwards-compatible bug fixes. * Additional labels for pre-release and build metadata are available as extensions to the MAJOR.MINOR.PATCH format. As the version number of Tcl has the same form MAJOR.MINOR.PATCH, nothing needs to be done here: future Tcl releases can be done following the Semantic Versioning rules. Tcl/Tk alpha/beta releases have the form MAJOR.MINOR[ab]PATCH, while Semantic Versioning dictates a form siminar to MAJOR.MINOR.0\(-alpha.\|-beta.\)PATCH: numeric and non-numeric parts must be preceded by a dash, and separated by additional dots. So, it is just a small step to adopt the Semantic Versioning idea. This TIP proposes to do just that, and describes the implications it has on Tcl and Tk. Alpha releases allow two forms of the version number, the semantic form MAJOR.MINOR.0-alpha.PATCH or the legacy form MAJOR.MINORaPATCH. For beta releases this will be MAJOR.MINOR.0-beta.PATCH resp MAJOR.MINORbPATCH. In Tcl 9.0, the legacy form might be removed and possibly enhanced to support all semantic versioning forms, but this is outside the scope of this TIP. Semantic Versioning will only be adopted for Tcl 8.7 and higher, so Tcl 8.5.x and 8.6.x will not be affected. This means that it is possible to introduce a minor new feature in 8.6.6, which would mandate a MINOR increment under the Semantic Versioning rules. This TIP doesn't apply to Tcl extensions either, each extension writer is free in whatever version strategy they choose. # Proposed Change This TIP proposes to adopt Semantic Versioning for Tcl and Tk 8.7 and higher. An exception will be made for Tcl extensions and Tcl modules, each extension and module author will be free to choose whether or not to adopt Semantic Versioning. Existing extensions/modules will continue to cooperate unchanged with future Tcl and Tk 8.x releases. One of the implications of this change is that there - most likely - will be future Tcl 8.7/8.8/8.9/8.10 releases. Since all Tcl minor releases can be installed next to each other, this would be a maintenance burden since all of those versions need to be maintained during serveral years in the future. Solution: drop the minor number from all Tcl and Tk filenames and installation directories. This way, Tcl 8.7 and 8.8 cannot be installed next to each other any more, they share the same installation directory if the installation _prefix_ is the same. Does that matter? No, because you always can choose a different prefix. Actually, there is no need for Tcl 8.7 any more when Tcl 8.8 is available, as they are 100% upwards compatible: the Semantic Versioning rules assure this. As soon as Tcl 8.8 is released, no new Tcl 8.7 releases will come out any more. Any incompatible change will have to wait for Tcl 9 \(or 10 or 11...\). Tcl 8.5 and 8.6 releases will continue to be supported as long as there is sufficient interest, this TIP doesn't change anything on that. An important implication of dropping the minor number in the Tcl installation script directory is that it would become "<prefix>/lib/tcl8" in stead of "<prefix>/lib/tcl8.7". This is a problem, because this is the same directory used for Tcl Modules, which still need to support existing extensions. This TIP therefore proposes to change TCL\_LIBRARY to '<prefix>/share/tcl8', that won't conflict with anything used thus far. Since Tcl now starts using TCL\_LIBRARY being a subdirectory of "<prefix>/share", it seems logical to start using this directory for man-pages as well. Therefore, it is proposed to upgrade "autoconf" to the latest version \(2.69\), which brings the man-page change without further hurdle. All together, the proposed directory structure \(UNIX\) > _<prefix>/bin/tclsh8_ **Tcl executable** > _<prefix>/lib/libtcl8.so_ **Tcl shared library** > _<prefix>/lib/tcl8_ **Tcl Modules** > _<prefix>/lib/tcl8/8.6_ > _<prefix>/lib/tcl8/8.7_ > _<prefix>/lib/tcl8.6_ **TCL\_LIBRARY for Tcl 8.6** > _<prefix>/share/tcl8_ **TCL\_LIBRARY for Tcl 8.x \(x>=7\)** > _<prefix>/share/man_ **Tcl manual pages** Regarding backporting, any change done in Tcl 8.7 could in principle be backported to Tcl 8.6 and further to 8.5, if desired. This TIP doesn't put a restriction to that, as Semantic Versioning only starts with version 8.7. Still it would be desirable for the TCT to describe a procedure for that, this is outside the scope of this TIP. Semantic Versioning requires that any API which is removed in Tcl 9.0 must be made deprecated in Tcl 8.7 \(or 8.8\). A new macro TCL\_DEPRECATED will be introduced for that in the \*Decls.h files. If Tcl 8.7 is compiled with the flag TCL\_NO\_DEPRECATED, all deprecated API is removed, by making those entries MODULE\_SCOPE, and putting 0 in the corresponding stub entries. This can be used by extensions to see whether they are compatible with the next major Tcl release or not. The following API's are declared deprecated in Tcl 8.7 and will be removed in Tcl 9.0. They are already removed in the "novem" branch: * Tcl\_Backslash * Tcl\_EvalFile * Tcl\_GetDefaultEncodingDir * Tcl\_SetDefaultEncodingDir * Tcl\_EvalTokens * Tcl\_CreateMathFunc * Tcl\_GetMathFuncInfo * Tcl\_ListMathFuncs An implementation of this TIP can be found at <http://core.tcl.tk/tcl> ; branch "semver". # Rejected Alternatives TODO # Copyright This document has been placed in the public domain. |
Name change from tip/44.tip to tip/44.md.
|
| < | < | | | | | | | > | | | | | | | | | | | | | < > | | | | | | | | | | | | | | | | | | | | | | | | < | > | | | | | | | | | | | | | | | | < > | < | > | | | | | | | | | | | > | 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 | # TIP 44: Move Tk's Private Commands and Variables into ::tk Namespace Author: Don Porter <[email protected]> State: Final Type: Project Vote: Done Created: 16-Jul-2001 Post-History: Tcl-Version: 8.4 ----- # Abstract This TIP proposes that Tk's private commands and variables be moved into the namespace _::tk_ or its descendent namespace\(s\). # Background Tk defines several commands and variables in the global namespace that are not intended for public use. Some of the commands are used for widget bindings. Some of the variables are used to maintain widget state information. The definition of these "private" commands and variables in the global namespace is a legacy held over from Tk 4 and the pre-8 versions of Tcl in which there was only one namespace. Fortunately, the coders of Tk have maintained good discipline in naming these commands and variables intended for Tk's internal use only. The commands and variables matching the glob pattern _::tk[A-Z]\*_ are private. Consider this interactive tktest session with Tk 8.3.3: $ cd tk/unix $ make runtest ... % # Put Tk through its paces to define all commands and variables % source ./../tests/all.tcl ... % llength [info commands {tk[A-Z]*}] 183 % llength [info vars {tk[A-Z]*}] 5 So, on Unix, there are 183 private commands and 5 private variables polluting the global namespace. The number and list of commands and variables varies a bit from platform to platform due to differences in widget bindings. More recently, private commands in Tk have been added in the _::tk_ namespace; two examples are _tk::PlaceWindow_ and _tk::SetFocusGrab_. Likewise the private variable _tk::FocusGrab_ has also been added in the _::tk_ namespace. There are three reasons why it is better for Tk's private commands and variables to be moved out of the global namespace and into the _::tk_ namespace. 1. The large number of commands and variable makes it more difficult to use interactive _[info commands]_ and _[info vars]_ or _[info globals]_ introspection to learn about what application specific commands and variables are defined. 2. Placing private commands and variables in the global namespace gives them a higher profile, and increases the likelihood that they will be used publicly, against the intent of Tk's interface. 3. By making more use of its own namespace for keeping track of its own internals, Tk becomes a better example for authors of other packages to copy. # Proposal All commands and variables created by Tk and matching the glob pattern _::tk[A-Z]\*_ shall be renamed to a name contained within the _::tk_ namespace or one of the descendent namespaces of _::tk_. The global variable _::histNum_ created by _tk/library/console.tcl_ shall also be renamed to _::tk::HistNum_. All commands and variables created by the proposal will be given names that begin with an uppercase character \(_[A-Z]_\) to indicate their internal status according to the conventions of the Tcl Style Guide <http://purl.org/tcl/home/doc/styleGuide.pdf> . # Compatibility and Migration This proposal only deals with the internals of Tk, so technically there are no compatibility issues, because Tk users should not be depending on these private commands and variables. That said, because these commands and variables have had a high profile in the global namespace, it seems likely that some users have written code that depends on them. To aid such users in a migration away from that dependence, it is also proposed that Tk provide two additional unsupported commands: ::tk::unsupported::ExposePrivateCommand commandName and ::tk::unsupported::ExposePrivateVariable variableName The command _[::tk::unsupported::ExposePrivateCommand commandName]_ restores the existence of the Tk private command _commandName_ in the global namespace as it was before adoption of this proposal. The command _[::tk::unsupported::ExposePrivateVariable variableName]_ restores the existence of the Tk private variable _variableName_ in the global namespace as it was before adoption of this proposal. For example, a Tk user who had written code that made use of the Tk private command _tkCancelRepeat_ can add the following code to continue working with Tk after acceptance of this proposal: if {![llength [info commands tkCancelRepeat]]} { tk::unsupported::ExposePrivateCommand tkCancelRepeat } These migration commands are in the namespace _tk::unsupported_, a new namespace to be used for unsupported commands in Tk. This namespace may and should be used for any other unsupported commands to be created in Tk. Their implementation is in the new file _tk/library/unsupported.tcl_. # Reference Implementation This proposal has already been implemented and committed to Tk's CVS repository on the branch tagged _dgp-privates-into-namespace_. That branch is up to date with Tk's HEAD branch as of July 16, 2001. To make an anonymous checkout of the reference implementation into a directory named _tkprivate_, run the following CVS commands: $ cvs -d :pserver:[email protected]:/cvsroot/tktoolkit \ login (Logging in to [email protected]) CVS password: <Enter> $ cvs -z3 -d :pserver:[email protected]:/cvsroot/tktoolkit \ co -r dgp-privates-into-namespace -d tkprivate tk The reference implementation has the same results on the Tk test suite as the HEAD revision. In the tktest of the reference implementation: $ make runtest ... % source ./../tests/all.tcl ... % llength [info commands {tk[A-Z]*}] 0 % llength [info vars {tk[A-Z]*}] 0 # See Also Feature Request 220936 <http://sf.net/tracker/?func=detail&aid=220936&group_id=12997&atid=362997> # Related Ideas / Future Work The ideas in this section are _not_ part of this proposal. They are related ideas mentioned here as explicitly outside the scope of this proposal so they will not be counter-proposed. * _Shouldn't Tk's public commands and variables be moved to ::tk too?_ > Well, yes, I think they should, but that change clearly involves sorting out more difficult compatibility/migration issues. The current proposal is limited to the less controversial topic of Tk's private commands and variables. We'll tackle the rest later. * _Shouldn't Tk make use of [namespace code] in its bindings?_ * _Wouldn't it make Tk better organized if commands like [tk::IconList_Add] were further renamed [tk::IconList::Add]?_ > Perhaps so. There may be many ways in which Tk can and should make better or more idiomatic use of namespaces. That's not the point of this proposal, though. The point is to get these commands and variables out of the global namespace. Once that is accomplished, then these other matters are unquestionably internal and can proceed at the discretion of the maintainers without further TIP review. # Copyright This document has been placed in the public domain. |
Name change from tip/440.tip to tip/440.md.
|
| < | < | | | | | | | | | > | | | | | | | | | | | > | 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 | # TIP 440: Add engine to tcl_platform Array Author: Joe Mistachkin <[email protected]> Author: Jan Nijtmans <[email protected]> State: Final Type: Project Vote: Done Created: 14-Jan-2016 Post-History: Keywords: language implementation,platform Tcl-Version: 8.5 ----- # Abstract This TIP proposes a mechanism for determining the implementation of the Tcl language currently in use. # Rationale There is more than one implementation of the Tcl language \(see <http://wiki.tcl.tk/13992> \). These implementations differ greatly in their degree of compatibility and completeness. At the script level, there is currently no standard way to determine which implementation of the Tcl language is being used. # Specification The **engine** element will be added to the **tcl\_platform** array. Its value will be set to **"Tcl"**. # Reference Implementation A reference implementation of this TIP is available <https://core.tcl.tk/tcl/timeline?r=tclPlatformEngine> . The TH1, Jim, Picol, JTcl, and Eagle implementations of the Tcl language already implement this feature, each using the name of the project as the value of the **tcl\_platform\(engine\)** element. # Copyright This document has been placed in the public domain. |
Name change from tip/441.tip to tip/441.md.
|
| < | < | | | | | | | | | > | | | | | | | | | | | | | | | | | > | 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 | # TIP 441: Add -justify Configuration Option to the listbox Widget Author: François Vogel <[email protected]> Author: François Vogel <[email protected]> State: Final Type: Project Vote: Done Created: 18-Jan-2016 Post-History: Keywords: Tk,listbox Tcl-Version: 8.6.5 ----- # Abstract Despite the **listbox** widget already having numerous configuration options, some users need more refinements and have requested the possibility to control the justification of the text displayed in the items of the listbox. This TIP proposes to add this option. # Rationale Currently the **listbox** widget always aligns its items leftwards. Some users miss a configuration options allowing to justify items in the **listbox** widget. These RFE include: * RFE 454303, <https://core.tcl.tk/tk/tktview/454303> * RFE 3f456a5bb9, <https://core.tcl.tk/tk/tktview/3f456a5bb9> # Proposed Change It is proposed to add the **-justify** configuration option to the Tk **listbox** widget. Possible values are as already documented in the **options** manual page \(i.e., **left**, **center**, or **right**\), and translate internally into standard _Tk\_Justify_ values, i.e., TK\_JUSTIFY\_LEFT, TK\_JUSTIFY\_CENTER, and TK\_JUSTIFY\_RIGHT, respectively. Default value is **left** on all platforms, for backwards compatibility reasons. # Reference Implementation A reference implementation is available in branch tip-441 of the fossil repository. # Copyright This document has been placed in the public domain. |
Name change from tip/442.tip to tip/442.md.
|
| < | < | | | | | | | | | | | > | | | | | | | | | | | | | | | | | | < < > > | | | | | | | | | | | | | | | > | 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 | # TIP 442: Display text in progressbars Author: René Zaumseil <[email protected]> Author: Kevin B Kenny <[email protected]> Author: Andreas Leitgeb <[email protected]> Author: Kevin Kenny <[email protected]> State: Final Type: Project Vote: Done Created: 17-Feb-2016 Post-History: Keywords: Tk Tcl-Version: 8.7 ----- # Abstract Horizontal progress bars should support the ability to display text inside the progress bar. Buttons should allow justification of multiline texts. # Rationale It is often useful to be able to display text directly on top of a progress bar. This text might be a description of the progress percentage, what is currently being done, or even just a label giving the overall task that is progressing. The **ttk::progressbar** command can easily enhanced to provide this support, and there is no interference with existing code as this functionality can be done by just introducing new options. The options required are from the list of usual Tk well-known option names. Also the **ttk::button** command can easily be enhanced to provide justification of multiline text. # Specification Text will be displayed only on horizontal **ttk::progressbar**. To control the text appearance the following new options will be added: -text: The string to display. -font: The font used to render the text. -foreground: The color of the text. -anchor: The anchoring of the text. -justify: The justification of the string. -wraplength: The length at which the string will be automatically wrapped. To justify multiline text in **ttk::button** a new option will be added: -justify: The justification of the string. # Notes for future improvements The underlying Tk text rendering engine supports rotated text, which would make support on vertical progress bars possible. But control of the rotation angle might be required \(according to whether the text is rotated left or right, or stays unrotated\). The most contrasting color of the text will depend where on the progress bar it is placed. This is not an effect that is simply reproduced with the Tk script level, but is easy to apply during rendering. # Implementation A patch implementing these changes and updating the documentation is available in the fossil repository in the tip-442 branch. Implementation is heavily borrowed from the **ttk::label** widget featuring these same options. The names, meanings, and default values of the options are the same as for **ttk::label**. The rendering and processing is the same as for this latter widget. # Example of use package require Tk proc moveit {} { for {set i 0} {$i < 100} {incr i} { .p step ; update ; after 100 } } pack [ttk::progressbar .p -value 0 -maximum 50 -orient horizontal -length 500] .p configure -anchor c -foreground blue -justify right \ -text "-anchor c -foreground blue -justify right -wraplength 100" \ -wraplength 100 moveit .p configure -anchor e -font {Arial 10 bold} -foreground green -justify center \ -text "-anchor e -font {Arial 10 bold} -foreground green -justify center -wraplength 250" \ -wraplength 250 moveit .p configure -text "-anchor w -foreground red -justify left -wraplength 50" \ -anchor w -foreground red -justify left -wraplength 50 moveit .p configure -orient vertical -text "Cannot be seen" moveit # Copyright This document has been placed in the public domain. |
Name change from tip/443.tip to tip/443.md.
|
| < | < | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 443: More Tag Configuration Options for the Text Widget Author: François Vogel <[email protected]> State: Final Type: Project Vote: Done Created: 09-Feb-2016 Post-History: Keywords: Tk Tcl-Version: 8.6.6 ----- # Abstract Despite the **text** widget already has numerous configuration options, some users need more refinements and have requested new tag configuration options. This TIP proposes to add these options, when deemed relevant. # Rationale Several users have reported they miss different tag configuration options in the **text** widget, stating they cannot achieve the rendering they target. Such RFE include: * RFE 1759972 <https://core.tcl.tk/tk/tktview/1759972> , with Patch 3469780 <https://core.tcl.tk/tk/tktview/3469780> * RFE 220889 <https://core.tcl.tk/tk/tktview/220889> * RFE 1754048 <https://core.tcl.tk/tk/tktview/1754048> # Proposed Change It is proposed to add the following tag configuration options to the Tk **text** widget: **-selectbackground** _color_: > Specifies the background color to use when displaying selected items. It may have any of the forms accepted by **Tk\_GetColor**. If _color_ has not been specified, or if it is specified as an empty string, then the color specified by the **-background** tag option is used. > Note regarding the particular case of the "sel" tag: Currently, the "sel" tag **-background** tag option is mirrored with the **-selectbackground** text widget option. This makes sense. It does not make real sense to have **-selectbackground** applied to the "sel" tag \(it is more intuitive to use **-background** for the "sel" tag\). However, if the "sel" tag receives non-empty **-selectbackground**, then this tag option prevails on the **-background** tag option for mirroring, i.e. the **-selectbackground** tag option is mirrored with the **-selectbackground** widget option. **-selectforeground** _color_: > Specifies the foreground color to use when displaying selected items. It may have any of the forms accepted by **Tk\_GetColor**. If _color_ has not been specified, or if it is specified as an empty string, then the color specified by the **-foreground** tag option is used. > Note regarding the particular case of the "sel" tag: same principle as above for **-selectbackground**. **-underlinefg** _color_: > Specifies the color to use when displaying the underline. It may have any of the forms accepted by **Tk\_GetColor**. If _color_ has not been specified, or if it is specified as an empty string, then the color specified by the **-foreground** tag option is used \(if there is one, otherwise the the color specified by the **-foreground** widget option is used\). **-overstrikefg** _color_: > Specifies the color to use when displaying the overstrike. It may have any of the forms accepted by **Tk\_GetColor**. If _color_ has not been specified, or if it is specified as an empty string, then the color specified by the **-foreground** tag option is used \(if there is one, otherwise the color specified by the **-foreground** widget option is used\). **-lmargincolor** _color_: > _Color_ specifies the background color to use in regions that do not contain characters because they are indented by **-lmargin1** or **-lmargin2**. It may have any of the forms accepted by **Tk\_GetColor**. If _color_ has not been specified, or if it is specified as an empty string, then the color specified by the **-background** widget option is used. **-rmargincolor** _color_: > _Color_ specifies the background color to use in regions that do not contain characters because they are indented by **-rmargin**. It may have any of the forms accepted by **Tk\_GetColor**. If _color_ has not been specified, or if it is specified as an empty string, then the color specified by the **-background** widget option is used. # Rejected additional tag configuration options RFE 1759972 <https://core.tcl.tk/tk/tktview/1759972> requested stippling \(**-selectbgstipple**, **-selectfgstipple**\) for selected text. Also RFE 1754048 <https://core.tcl.tk/tk/tktview/1754048> requested stippling in left and right margins of the text widget \(**-lmargin1stipple**, **-lmargin2stipple**, **rmarginstipple**\). Any new stippling options was rejected during the discussion about this TIP. Reasons were as follows: * "Stippling and anything related to Tk Bitmaps should be considered obsolete. Their use should be phased out, not expanded. \(Bitmaps have very limited support in Tk, and stippling is virtually never used in modern user interfaces. In fact, AFAIK current graphics stacks -- cairo, Quartz, Direct3D, &c -- don't even support this operation." * "Stippling is something that is an artefact of a prior time, and it looks pretty bad now. These days, a way to specify an alpha value for the tag would be far more relevant, since then it would end up with a blend of the text foreground and background." # Reference Implementation A reference implementation is available in branch tip-443 of the fossil repository. # Copyright This document has been placed in the public domain. |
Name change from tip/444.tip to tip/444.md.
|
| < | < | | | | | | | > | | | | | | | | | | | | | | | > | 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 | # TIP 444: Add "weekdays" unit in clock add Author: Pietro Cerutti <[email protected]> State: Final Type: Project Vote: Done Created: 23-Feb-2016 Post-History: Tcl-Version: 8.7 ----- # Abstract This TIP proposes an enhancement to the **clock add** command to support performing days arithmetic using weekdays only. # Rationale The **clock add** command allows to perform time arithmetic using a variety of time units, including days. However, it offers no easy way to skip weekends. It is often desired to perform weekdays arithmetic that involves adding or subtracting a number of non-weekend days to a certain date. This is useful in example when computing delivery dates. # Proposal The **weekdays** time-unit is added to the list accepted by the **clock add** command. The **count** argument represents weekdays \(Mon-Fri\) to be added \(or subtracted in case of a negative value\) to the date. The result of adding weekdays to a date is never a weekend day, unless the starting day is itself a weekend day and **count** is 0. # Reference Implementation Available at <http://core.tcl.tk/tcl/timeline?t=tip-444> # Discussion A point has been raised as to whether _weekday_ is unambiguous enough. For instance, in Sweden there seems to be some disagreement on whether the translation _vardag_ includes Saturdays. As an alternative, the term _workday_ has been mentioned. This, however, has the downside of introducing the concept of working days vs. public holiday. Also, the working week is not Mon-Fri in all countries, see <https://en.wikipedia.org/wiki/Workweek_and_weekend#Around_the_world> . TIP does not try to accomodate locale-specific features and characteristics. For this reason, it seems best to stick to _weekday_ as the name of the unit and specifically mention that \(Mon-Fri\) is intended in the documentation. # Copyright This document has been placed in the public domain. |
Name change from tip/445.tip to tip/445.md.
|
| < | < | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 445: Tcl_ObjType Utility Routines Author: Don Porter <[email protected]> State: Draft Type: Project Vote: Pending Created: 18-Mar-2016 Post-History: Tcl-Version: 8.7 ----- # Abstract Proposes additional public routines useful for extensions that implement custom **Tcl\_ObjType_s. # Background When an extension creates a custom **Tcl\_ObjType** it needs to operate on the fields of the **Tcl\_Obj** and the **Tcl\_ObjType** structs. Almost all of these operations have been nicely encapsulated in utility routines, so for example, an extension calls **Tcl\_GetString** to make sure a value is set for _objPtr->bytes_, rather than worrying about the backing details of calling the routine _objPtr->typePtr->updateStringProc_ \(if present\) for itself. Likewise **Tcl\_DuplicateObj** routes processing to type-specific routines as needed. There are gaps in this interface. Most glaring is the lack of any way to call the _freeIntRepProc_ of an incumbent type other than directly through the _typePtr_ field. Another missing bit is an encapsulated way to set the string rep without direct manipulation of the _bytes_ and _length_ fields. Within Tcl itself, there are internal utility macros **TclFreeIntRep** and **TclInitStringRep** for these tasks, but extensions have nothing. Besides convenience, utility routines such as these improve chances for correctness, since they bring constraints into one place instead of many places. For example, the requirement that when _objPtr->typePtr_ is not NULL, it must be paired with an appropriate _objPtr->internalRep_. The **TclFreeIntRep** macro has a history of fixing such bugs. A corresponding routine will offer the same benefit to extensions. # Proposal Add to Tcl's stub table of public C routines a new routine > void **Tcl\_FreeIntRep**\(Tcl\_Obj\* _objPtr_\) that performs precisely the same task as the existing internal macro **TclFreeIntRep**. Add to Tcl's stub table of public C routines a new routine > char \* **Tcl\_InitStringRep**\(Tcl\_Obj\* _objPtr_, const char\* _bytes_, unsigned int _numBytes_\) that performs the function of the existing internal macro **TclInitStringRep**, but is extended to return a pointer to the string rep, and to accept NULL as a value for _bytes_. When _bytes_ is NULL and _objPtr_ has no string rep, an uninitialzed buffer of _numBytes_ bytes is created for filling by the caller. When _bytes_ is NULL and _objPtr_ has a string rep, the string rep will be truncated to a length of _numBytes_ bytes. When _numBytes_ is greater than zero, and the returned pointer is NULL, that indicates a failure to allocate memory for the string representation. The caller may then choose whether to raise an error or panic. Add to Tcl's stub table of public C routines a new routine > int **Tcl\_HasStringRep**\(Tcl\_Obj\* _objPtr_\) that returns a boolean indicating whether or not a string rep is currently stored in _objPtr_. This is used when the caller wants to act on _objPtr_ differently depending on whether or not it is a _pure_ value. Typically this only makes sense in an extension if it is already known that _objPtr_ possesses an internal type that is managed by the extension. Define a new public type > typedef union **Tcl\_ObjIntRep** \{...\} **Tcl\_ObjIntRep** where the contents are exactly the existing contents of the union in the _internalRep_ field of the **Tcl\_Obj** struct. This definition permits us to pass internal representations and pointers to them as arguments and results in public routines. Add to Tcl's stub table of public C routines a new routine > void **Tcl\_StoreIntRep**\(Tcl\_Obj\* _objPtr_, const Tcl\_ObjType\* _typePtr_, const Tcl\_ObjIntRep\* _irPtr_\) which stores in _objPtr_ a copy of the internal representation pointed to by _irPtr_ and sets its type to _typePtr_. When _irPtr_ is NULL, this leaves _objPtr_ without a representation for type _typePtr_. Add to Tcl's stub table of public C routines a new routine > Tcl\_ObjIntRep\* **Tcl\_FetchIntRep**\(Tcl\_Obj\* _objPtr_, const Tcl\_ObjType\* _typePtr_\) which returns a pointer to the internal representation stored in _objPtr_ that matches the requested type _typePtr_. # Compatibility These are new routines, so they have no compatibility concerns in the sense of cause trouble for existing working code. They do help set up an improved compatibility scenario for the future however. Extensions that use these new routines to stop directly referring to the fields of the **Tcl\_Obj** and **Tcl\_ObjType** structs are prepared to support a source-compatible migration to a Tcl 9 that might then be free to make revisions to those structs. # Implementation Taking shape on the tip-445 branch. # Rejected Alternatives # Copyright This document has been placed in the public domain. |
Name change from tip/446.tip to tip/446.md.
|
| < | < | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | < > | | | | | | | | | < > | < > | | | | | | | < > | < > | | | | | | | | | | | > | 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 | # TIP 446: Introspect Undo/Redo Stack Depths Author: François Vogel <[email protected]> State: Final Type: Project Vote: Done Created: 05-Apr-2016 Post-History: Keywords: Tk Tcl-Version: 8.6.6 ----- # Abstract Tk features a generic undo/redo mechanism \(see [[104]](104.md)\). This is used in practice by the **text** widget, within the **edit** command. The present TIP proposes to add two new subcommands to the **edit** command allowing the user to know whether undo and redo is possible for a **text** widget. # Rationale The undo/redo feature of Tk is handy and works very well. In modern GUIs, there is usually a button in a menubar to call the "Undo" command, and likewise for "Redo". It is good practice to enhance the user experience by greying out or otherwise changing the button aspect when there is nothing to undo \(or redo\). This cannot be achieved currently with the curent Tk implementation because there is no way to know whether the undo and redo stacks are empty or not. This feature was requested for the text widget in RFE 1273358 <https://core.tcl.tk/tk/tktview/1273358> # Proposed Change It is proposed to add the following subcommands to the **text** widget's **edit** command: **canundo**: > Returns a boolean true if undo is possible, i.e. when the undo stack is not empty. Otherwise returns false. **canredo**: > Returns a boolean true if redo is possible, i.e. when the undo stack is not empty. Otherwise returns false. When the **-undo** option of the text widget is false both subcommands return false since indeed no undo nor redo action is possible in this case. The undo/redo stacks are however not cleared, so that when -undo becomes eventually true again the two new subcommands will return their value in accordance with the contents of the stacks \(this is current behavior of the undo/redo feature - the TIP does not intend to change this\). This new capability will be implemented in the generic code for undo \(_generic/tkUndo.c_\), so that any client of the generic undo/redo mechanism can make use of it. Currently, only the **text** widget is concerned since no other Tk widget is featuring undo/redo. Besides the two new subcommands, it is also proposed to add a new virtual event **<<UndoStack>>**, that will trigger each time the undo or redo stack becomes empty or unempty. When this condition is met, the event will trigger once for each peer widget. Despite this is a new feature, this TIP targets Tk 8.6.6 since no change of any existing behavior is proposed: only new, additonal, features are proposed. It is therefore believed there is no risk regarding backwards compatibility in the 8.6.x series. # Example package require Tk pack [text .t -undo false -autoseparators false] set nbUS 0 bind .t <<UndoStack>> {incr nbUS} .t edit canundo ; # 0 .t edit canredo ; # 0 .t configure -undo true .t edit canundo ; # 0 .t edit canredo ; # 0 .t insert end "ABC\n" .t edit separator .t insert end "DEF\n" .t insert end "DEF again\n" .t edit separator .t edit canundo ; # 1 .t edit canredo ; # 0 .t edit undo .t edit canundo ; # 1 .t edit canredo ; # 1 # A quick interactive testing environment...: pack [label .l] proc showit {} { global nbUS .l configure -text "Can undo: [.t edit canundo]\t\t\t \ Can redo: [.t edit canredo]\t\t\t \ <<UndoStack>> triggered: $nbUS" after 200 showit } showit proc toggleautosep {} { global autosepset set autosepset [.t cget -autoseparators] if {$autosepset} { .t configure -autoseparators false } else { .t configure -autoseparators true } set autosepset [.t cget -autoseparators] } proc toggleundo {} { global undoset set undoset [.t cget -undo] if {$undoset} { .t configure -undo false } else { .t configure -undo true } set undoset [.t cget -undo] } button .b1 -text "Insert separator" -command {.t edit separator} button .b2 -text "Undo" -command {.t edit undo} button .b3 -text "Redo" -command {.t edit redo} button .b32 -text "Reset" -command {.t edit reset} checkbutton .b4 -text "-autoseparators" -command toggleautosep -variable autosepset checkbutton .b5 -text "-undo" -command toggleundo -variable undoset ; .b5 select pack .b1 .b2 .b3 .b32 .b4 .b5 -side left -padx 10 # Reference Implementation A reference implementation is available in branch tip-446 of the fossil repository. Credits for this implementation largely go to Neil Hodgson, the author of TkTextPlus \(for canundo/canredo\) and to Koen Danckaert \(for <<UndoStack>>\). # Copyright This document has been placed in the public domain. |
Name change from tip/447.tip to tip/447.md.
|
| < | < | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | < > | < > | | | | | | | | > | 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 | # TIP 447: Execution Time Verbosity Levels in tcltest::configure Author: Pietro Cerutti <[email protected]> State: Final Type: Project Vote: Done Created: 20-Apr-2016 Post-History: Keywords: Tcl,tcltest Tcl-Version: 8.7 ----- # Abstract The **-verbose** option of the **tcltest::configure** command accepts a set of verbosity levels to specify what pieces of information about tests the user wants reported. This TIP proposes the addition of two new verbosity levels to report information about the execution time of tests. # Rationale When doing test-driven development, working on the refinement of a new feature, or fixing a bug, it is very important to be able to measure the effect of code changes on execution time. The **tcltest** infrastructure is the testing framework used both by Tcl/Tk and a number of extensions. The **tcltest** infrastructure is highly configurable and allows the user to choose which information on the tests being run are reported. This can be done with the **-verbose** option of the **tcltest::configure** command. Verbosity levels allow to report, e.g., when a test passes, is skipped, or fails. A proper way to measure the time spent running each test is currently missing. Scope of this TIP is to address this issue by extending the set of verbosity levels accepted. # Proposal The **-verbose** option of the **tcltest::configure** command is modified to accept the following new verbosity levels: usec \(u\): Report execution time of each test, in microseconds. msec \(m\): Report the execution time of each test, in milliseconds. # Example This example demonstrates running a subset of the Tcl test suite with verbosity level **usec** \(**u**\): $ make TESTFLAGS="-verbose u -match lsearch-1.*" test ... lsearch.test ++++ lsearch-1.1 took 521 us ++++ lsearch-1.2 took 156 us ++++ lsearch-1.3 took 187 us ++++ lsearch-1.4 took 120 us # Discussion ## Additional Time Units The implementation of additional verbosity levels to track execution times in seconds, minutes, hours, and so on is trivial, but has been discarded as unit or functional test are often meant to be fast. Another approach would be to introduce a configurable verbosity level to carry information on the time unit to be used. Examples could be **time:usec**, **time:msec**, and **time:sec**. This option has also been discarded because it clashes with the current approach of having verbosity level strings that can be shortened to a single character. It is the author's opinion that milliseconds and microseconds should address most use cases. ## When Timing Should be Displayed? The current implementation dumps timing information before any reports of success / failure. Example: ---- tsv-lmdb-1.5 start ++++ tsv-lmdb-1.5 took 828 us ==== tsv-lmdb-1.5 tsv::exists - previously set exists FAILED ---- Result was: 1 ---- Result should have been (exact matching): 0 ==== tsv-lmdb-1.5 FAILED This allows for a simpler implementation that doesn't need to account for the different code paths taken by **tcltest** when reporting success or failure. The author doesn't have a strong opinion on this matter and is open to discussion, should anybody have any counter-proposal. ## What to Print? The current implementation decision to print "<testname> took <amount> <unit>" is arbitrary. Again, the author has no strong opinion on the subject. ## On the Goodness of the Times Reported FV, DGP, and and DKF have raised concerns on the mailing lists on the goodness of the time values reported by the **msec** and **usec** verbosity levels. In particular, the problem of repeatibility of the results has been mentioned, and it has been noted that while the idea is good, this might not be the right tool for \(the\|every\) job. My opinion is that the tool can be useful, given that its scope is made clear. I followed DGP's suggestion and added [checkin 2b96ef] an explicit note in the documentation about the "modest ambitions" of this enhancement. # Reference Implementation In the gahr-tip-447 branch. # Copyright This document has been placed in the public domain. |
Name change from tip/448.tip to tip/448.md.
|
| < | < | | | | | | | | > | | | | | | | | | | | > | 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 | # TIP 448: Update Tcl_SetNotifier to Reinitialize Event Loop Author: Jeff Rogers <[email protected]> State: Draft Type: Project Tcl-Version: 8.7 Vote: Pending Created: 24-May-2016 Post-History: Keywords: Tcl, C API ----- # Abstract Tcl\_SetNotifier cannot be used in its current state to replace a notifier than has been initialized because pointers to the old initialized value are kept in the interp's private data. This TIP proposes a way to change that. # Background The **Tcl\_SetNotifier** API was introduced to allow replacement of the built-in notifier; it works by setting hooks for various notifier functions that are called in place of the builtin functions. It was expected that this function would only be called before the Tcl library had been initialized and any state had been set up; however this prevents it from being usable from a module loaded by a running interpreter. This TIP proposes changing the behavior of this API to, in addition to setting the function hooks will shut down a running notifier and restart the notifier if it has been running previously. This is the minimum change necessary to allow a new notifier to be loaded from within a running interpreter. It is probably not always possible to stop a running notifier, especially if event sources have been created. It is not necessarily easy to detect such failure; the proposed implementation doesn't even try. And there is no way to report such failure if it was detected. As such, this remains a somewhat dangerous interface to use. With this change in place, it will be possible to load a new notifier implementation \(e.g., a _poll\(\)_ or _libevent_ based one\) from a Tcl program, provided it is the very first thing done. An implementation of a poll-based notifier that requires the functionality in this TIP can be found at <http://fossil.etoyoc.com/sandbox/tcllib/artifact/ad30080cdee762a3> # Description Change the implementation of **Tcl\_SetNotifier** to check if a notifier is currently running; if it is, the current notifier will be finalized before the new hooks are swapped in, and afterwards the notifier will be re-initialized. If the notifier is not already initialized, there is no change to functionality. # Implementation A patch implementing the proposed change can be found at <http://fossil.etoyoc.com/sandbox/tcllib/artifact/b2b272a285811272> # Copyright This document has been placed in the public domain. |
Name change from tip/449.tip to tip/449.md.
|
| < | < | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 449: [text] undo/redo to Return Range of Characters Author: François Vogel <[email protected]> State: Final Type: Project Vote: Done Created: 07-Jun-2016 Post-History: Keywords: Tk Tcl-Version: 8.7 ----- # Abstract Tk features an undo/redo mechanism for the **text** widget. This TIP proposes that the **edit undo** and **edit redo** commands of the text widget return the ranges of characters impacted by the undo or redo operation. # Rationale In some applications using the **text** widget, say a text editor, modern practice is to show the text with highlighting, colorization, or any other ways of improving readablity for the human user. When undoing/redoing changes in the text, these applications need to know which characters were impacted by the undo or redo operation. This can be done by comparing the **text** widget contents before the change with its contents after the change, but this is very far from optimal especially with large texts. Therefore a better way to get this information is proposed in the present TIP. This feature was requested for the text widget in RFE 1217222 <https://core.tcl.tk/tk/tktview/1217222> # Proposed Change Currently, **edit undo** and **edit redo** commands return the empty string. It is proposed to change this return value and make these commands return the ranges of indices that were impacted by the undo or redo operation. This return value is a list of indices, with an even number of elements. Indeed, there can be several edits \(insertions and deletions\) between two separators in the undo stack and all such edits have to report which range of text they changed. The returned ranges are made of indices making sense at undo/redo return time, i.e. they refer to the text widget content at the time **edit undo** and **edit redo** return. Moreover, the returned list of indices is optimal, in the sense that the ranges contained in that list are all disjoint \(overlapping ranges are merged, and ranges already contained in another range are not returned\). # Backwards Compatibility The proposed implementation makes use of temporary marks, that only exist _during_ an undo or redo operation \(and never before or after these operations\). This could be seen as a concern regarding backwards compatibility, however it is believed that the names of these marks has been chosen such that this should not be an issue. The chosen name is **tk::undoMark<g><ID>**, where **<g>** is either **L** or **R**, and **<ID>** is an integer identifier. The risk of name collision is therefore deemed very low due to prefixing by **tk::**. This naming convention follows what is already existing in the text widget \(internal anchors\). # Example package require Tk pack [text .t -undo true] .t insert end "Hello World.\n" .t edit separator .t insert end "Again hello.\n" .t edit undo ; # will now return {2.0 3.0} .t edit redo ; # will now return {2.0 3.0} More examples can be found by studying the new tests in the feature branch tip-449 hosting the development. # Reference Implementation A reference implementation is available in branch tip-449 of the Tk fossil repository. This new capability is implemented entirely in the code of the text widget. The undo/redo generic code \(in _generic/tkUndo.c_\) is untouched. # Copyright This document has been placed in the public domain. |
Name change from tip/45.tip to tip/45.md.
|
| < | < | | | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 45: Empty index lists for [lindex] and [lset] Author: Kevin Kenny <[email protected]> Author: Don Porter <[email protected]> State: Final Type: Project Vote: Done Created: 18-Jul-2001 Post-History: Discussions-To: news:comp.lang.tcl,mailto:[email protected] Keywords: lindex,lset,multiple arguments,sublists Tcl-Version: 8.4b1 ----- # Abstract TIP's \#22 and \#33 contain an oversight in specifying the behavior of the multi-argument forms of _lset_ and _lindex_ when an empty index list is specified. The intended behavior is that an empty list of indices designates the entire list. # Rationale In the discussion of [[33]](33.md) \(<http://www.geocrawler.com/archives/3/7375/2001/5/0/5784409/> \), Jim Ingham pointed out that the list of indices presented to the multi-argument forms of _lindex_ and _lset_ is analogous to a database cursor. This cursor is conceptually navigating a tree structure; the command: lindex $list {1 2 3} means, "extract the sublist at index 1 in $list, the sublist at index 2 in that list, and the element at index 3 in that list". When implementing this functionality, the author of this TIP realized that [[22]](22.md) and [[33]](33.md) provide no way to address the root of the tree -- the entire list being manipulated. An empty list of indices is a convenient means of specifying the root. # Specification 1. The specification of _lindex_ in [[22]](22.md) shall be amended so that the forms: lindex list > and lindex list {} > will return the value of the entire list. The _list_ parameter is not required to be a well-formed Tcl list when this form is used. 1. The specification of _lset_ in [[33]](33.md) shall be amended so that the forms: lset var value > and lset var {} value > will simply store the supplied value into the variable named _var_. Neither the old nor the new value of _var_ is required to be a well-formed Tcl list when this form is used. The return value of the operation, as with all other uses of _lset_, is the new value of _var_. # Reference implementation Work progresses on implementing this functionality; the currently committed version is on SourceForge in the branch labeled, _kennykb-tcl-22-33_. # Discussion Since this proposed change introduces syntax that is expressly forbidden in [[22]](22.md) and [[33]](33.md), it does not have any impact on backward compatibility. For the same reason, the author thought it unwise to proceed with its implementation without a vote of the TCT. # See Also [[22]](22.md), [[33]](33.md). # Copyright This document has been placed in the public domain. |
Name change from tip/450.tip to tip/450.md.
|
| < | < | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 450: Add [binary] subcommand "set" for in-place modification Author: Arjen Markus <[email protected]> State: Draft Type: Project Vote: Pending Created: 18-Jul-2016 Post-History: Tcl-Version: 8.7 Keywords: Tcl, binary data ----- # Abstract This TIP proposes a simpler extension of the [binary] command than the related [[418]](418.md), namely just a subcommand **set** that updates an existing byte array in a variable instead of creating a new one like **binary format**. It does not propose an extension of the various formatting codes. # Rationale As already argued in [[418]](418.md), the **binary** command is efficient in creating new objects of binary data or in parsing existing objects with such data. It is not currently efficient in _updating_ existing objects. However, such data objects are commonly used by compiled extensions. As a consequence, if you want to manipulate such data objects from Tcl directly, it is easier to parse the object into, say, a list of numbers, use list commands like **lset** to replace individual values and pack it into a new binary array before passing it to a compiled extension. # Specification This TIP proposes to add a subcommand **set** to the **binary** command with the following signature: > **binary set** _varName formatString arg1 arg2 arg3 ..._ The effect of this subcommand is that the byte array data contained in the variable "varName" is updated in a manner analogous to **lset**, but using a format string like **binary format**. It could be implemented in Tcl as: > set varName [binary format "a*$formatString" $varName $arg1 $arg2 $arg3 ...] except that this allocates a new block of memory, sets that to null, copies the contents of _varName_ into that new block and then does the update. The new command will have the effect that the first few steps are not necessary anymore. # Implementation Notes Besides the nominal case of a variable that contains a binary array that is to be updated within the bounds of that array, three other cases exist and need to be prepared for: * The variable varName does not exist yet * The variable varName does not contain a binary array * The updating would go past the memory allocated for the binary array Each of these cases and perhaps others will have to be taken care of. The first case might be treated as if **binary format** was meant. For the second case the implementation can convert the current value. The third case might either cause an error \(we are updating an existing block of memory after all\) or silently extend the memory, effectively performing what the Tcl implementation shown above would do. If an error is thrown, then the first case should probably throw an error as well. # Reference Implementation To be committed to a fossil branch. A few remarks: * The third case is not completely treated yet \(see "TODO" in the code\) * The **binary set** command does not properly invalidate the string representation. The binary array is, however, updated properly - at least according to the very limited tests that were performed. * There are no proper test cases yet. * There is no proper performance measurement yet; this could be based on Wiki page <http://wiki.tcl.tk/44363.> * It does not deal with the possibility that the binary array is shared. # Copyright This document is placed in public domain. |
Name change from tip/451.tip to tip/451.md.
|
| < | < | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 451: Modify [update] to Give Full Script Access to Tcl_DoOneEvent Author: Colin McCormack <[email protected]> State: Draft Type: Project Vote: Pending Created: 10-Aug-2016 Post-History: Keywords: Tcl,event loop Tcl-Version: 8.7 ----- # Abstract This TIP add flags to **update** to represent all the flag values available to the underlying API, _Tcl\_DoOneEvent\(\)_, exposing them to script access. # Rationale The **update** command provides a way into the event loop in addition to **vwait**. Because the Tcl event system derived historically from Tk, **update** was written specifically to support Tk's window and idle events. When Tcl adopted the event system for timers and file events, the **update** command was anomalously not updated to cater for these new event types. The reason this anomaly is worth correcting is that Tcl\_DoOneEvent is the actual entry into the event loop and there is no good or sufficient reason for **update** to limit the flags to those specific to Tk only. While **vwait** provides a reasonable way into and out of the event loop, there's no good reason to impose that communication mechanism on the application when there are other approaches possible, arguably more useful, and amply provided for by the underlying C implementation. # Proposal The **update** command should have the following flags added to it: * **idletasks** - process any pending window events or idle events, do not wait \(this is as currently supported\) * **window** - process window events * **file** - process file events * **timer** - process timer events * **onlyidle** - process only idle events * **all** - process all events * **wait** - wait until at least one event has been processed * **nowait** - return immediately if no events are pending. and they should be painted Pantone 13-1520 The somewhat klunky and denormalised logical form of these flags is imposed by the requirement to minimally disrupt existing **update** functionality. # Reference Implementation A reference implementation is available in Tcl core fossil under tag _updateextended_. # Use Case 1 Application of **after idle** constructs a collection of _idle tasks._ An _idle task_ represents something to be performed when no events are pending. This proposal exposes the idle state directly to a Tcl script and the application can do what it will in that state. Use Case Summary: "I would like to handle _idle tasks_ in some particular or specific order, at script level." # Use Case 2 A script may have accepted network file i/o for some time, and have a number of pending background \(aka idle\) tasks to perform as a result of that i/o. It may wish to throttle acceptance of connections, or further read events, pending that background processing. Use Case Summary: As a special case of "I would like direct control over my 'idle' time.", "I would like to throttle network input." # Rejected Alternatives One could create a new command for this functionality, but the minimal impact on most Tcl users doesn't seem to me to warrant additional population of the :: command namespace. One could move **update** out of Tcl altogether \(to avoid its explicit dependency on Tk events\) into Tk. This would open up the :: namespace to a more general event-handling mechanism. # Copyright This document has been placed in the public domain. In legislations where this concept does not exist the CC0 license applies. |
Name change from tip/452.tip to tip/452.md.
|
| < | < | | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 452: Add "stubs" Package to or Along Side of TclTest Author: Gerald Lester <[email protected]> Author: Gerald W. Lester <[email protected]> Author: Gerald W. Lester <[email protected]> State: Draft Type: Project Vote: Pending Created: 10-Aug-2016 Post-History: Tcl-Version: 8.6 ----- # Abstract This TIP proposes an enhancement to the **tcltest** package to add support for easy creation of test stubs, mocks and seams. # Rationale The **tcltest** package allows for automated testing of Tcl code. However, doing proper automated unit testing requires that the unit under test \(i.e., the method or procedure\) not invoke the actual implementation of other units, but rather should invoke stub or mock units that are under the control of the test being performed as to the results they return and any exceptions they raise. This TIP adds support for building these mechanisms, making it significantly easier to create isolated unit tests of Tcl code. # Proposal That a framework to easily create test stubs/mocks of Tcl commands be added to the **tcltest_ package. Additionally, to facilitate the creation of automated test for legacy Tcl code. Commands supporting _test seam_ creation and specification would also be included proposed package. ## Description It provides a fully functional implementation of the following commands: * **::tcltest::TestSetup** - Defines which procedures/commands are stubbed out and how they should behave for each invocation. This should only be called once per test. * **::tcltest::AddStub** - Adds a procedures/commands to the list that are stubbed out. * **::tcltest::SaveVars** - Saves the values of variables to be restored later. This should only be called once per test. * **::tcltest::AddVars** - Add a variable to the list of variables to be restored later * **::tcltest::CallCount** - Returns a dictionary sorted list of the stubbed out procedures and how many times they were called. * **::tcltest::TestCleanup** - Restores saved variables and stubbed out procedures. * **::tcltest::SortedArrayData** - Return the values of an array as a list of key-value pairs sorted by the keys. * **::tcltest::CallProc** - Call the real implementation of a stubbed out procedure. * **::tcltest::Seam** - Test seam definition and injection \(aka enabling\). This command is available without requiring the tcltest package. # Reference Implementation See the tip-452 branch \(<http://core.tcl.tk/tcl/timeline?n=100&r=tip-452\),> in particular, see http-tip-452.test for an example of using the procedures added by this package. ## Origins of Reference Implementation The reference implementation was done at SAP Labs, LLC \(a subsidiary of SAP Americal, Inc.\) and approved for release as Open Source under a BSD license. # Copyright This document has been placed in the public domain. |
Name change from tip/453.tip to tip/453.md.
|
| < | < | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | < > | | | | | | | | | < < | > > | | | | | | | < > | | | | | | | | > | 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 | # TIP 453: Tcl Based Automation for tcl/pkgs Author: Sean Woods <[email protected]> State: Draft Type: Project Vote: Pending Created: 13-Sep-2016 Post-History: Keywords: Build tooling Tcl-Version: 8.7 ----- # Abstract This TIP proposes replacing the **make package** process currently employed by the core with a Tcl-based build automation tool. # Background [[376]](376.md) provides for the distribution of third party packages in the Tcl/Tk core distributions. To support that TIP currently requires three separate build automations: a Makefile based automation in Unix, and both an nmake and Makefile based automation for Windows. These automation systems can get out of sync and they assume that their job is to build dynamic libraries for local installation. # The Pitch By the time **make packages** has run, the local Tcl interpreter has been built already. Rather than rely on delicate hacks and makefile tricks, core distributed packages could be built and installed via exec commands inside a Tcl script. In addition, this same automation could handle functions like injecting a core distributed package into a virtual file system, as well as bundling the Tcl/Tk library file system for [[430]](430.md). # The Implementation For the _practcl_ branch of tclconfig, I put together a 4000 line self-contained package and kit building library of tools. This library is TclOO based, and provides a rudimentary \(but functional\) system for templating C code in Tcl, as well as a build system that is capable of nesting sub-projects. It also steals the useful bits from the **fileutil** module of tcllib, providing implementations for concatenating files, performing file searches, and building a global package index from a soup of modules. The library also has a wrapper to download external sources from fossil. It also contains procs that can compile a static library, dynamic library, or self contained shell directly from exec calls. I would propose that this tool system \(or a new creation by the community in a similar spirit\) be included in the library/ section of the tcl core. The provisional name for this tool set would be **practcl**. A version of this tool could also be provided in tcllib to allow 8.5 and 8.6 based cores to continue to build extensions. In the new scheme, **make packages** \(in all its forms\) would be replaced with a call to "_$\(TCLSH\) $\{srcdir\}/pkgs/make.tcl build_". **make packages-install** would be replaced by a call to "_$\(TCLSH\) $\{srcdir\}/pkgs/make.tcl install_". For advanced users, these toplevel commands **build** and **install** will accept additional arguments. For instance, to install the core distributed packages into the VFS of a kit: "_$\(TCLSH\) $\{srcdir\}/make.tcl install -destdir $\{MyVFS\}/lib_". # pkgs/make.tcl **make.tcl** would be maintained as part of the core, and provide the top-level control system to build, install, or repackage the core distributed extensions. That script will also provide mechanisms to populate the pkgs file system for developers who build the tcl core from fossil checkouts. Commands: * **basekit** > Compile a ZipFs style basekit suitable for the **wrap** command. * **build** ?**all**? ?_package_? ?_package..._? > Compile the source code for core distributed packages into binary products \(as applicable.\) If **all** is given, an attempt is made to compile all packages under _pkgs/_. Any other argument is interpreted to be the name of an individual package to be compiled. * **install** ?**-destdir** _destinationpath_? > Install all core distributed packages locally. If **-destdir** is given, install the packages relative to _destinationpath_ in the same way that "**make DESTDIR=** _destdir_" would. If **-destdir** is not given, or is an empty string, perform an install relative to the **exec\_prefix** in **tclConfig.sh** * **wrap** _exename_ _vfspath_ ?_dir..._? > Generate a self contained executable constructed from the virtual file system amalgamated from _vfspath_ and any other directories given as arguments. This VFS will automatically be populated with the **library/** file system from Tcl. * **distribution** > Download packages listed in the "packages.tcl" file, unpack their source code in the /pkgs folder, and perform any steps required to prepare those extensions for inclusion in a core snapshot for distribution. * **developer** > Download packages listed in the "packages.tcl" file, unpack their source code in the parent folder to the one the core has been unpacked from, and perform any steps required to prepare those extensions to be compiled locally as part of a developer build. This is intended for developers who work from fossil checkouts of the Tcl core. * **package-list** > Stream to stdout a list of all of the packages in the packages.tcl file, in a flat machine readable format. # Tk This same mechanism will be adapted for Tk. Tk will be also provide a **pkgs/** directory. Its base kits will be based on a modified _wish_ instead of a modified _tclsh_. # Normal Operation During the build/install/etc phase each directory will be scanned for either a "configure" file or a "prac.tcl" file. Standard TEA extensions will be detected by the presence of a "configure" file. The prac.tcl file is a hint to the build system that the package needs either additional instructions and guidance. The contents of the file are interpreted by the object which is implementing the extension's ambassador to the build system. If one were to decide to bundle tcllib, and wished to exercise its SAK based installer the prac.tcl file would read: # Implement the install routine for tcllib # oo::objdefine [self] { method install DEST { set pkg [my define get pkg_name [my define get name]] my unpack set prefix [string trimleft [my <project> define get prefix] /] set srcdir [my define get srcdir] ::practcl::dotclexec [file join $srcdir installer.tcl] \ -pkg-path [file join $DEST $prefix lib $pkg] \ -no-examples -no-html -no-nroff \ -no-wait -no-gui -no-apps } } # Maintaining the Package List Each **pkgs/** file system for both Tcl and Tk will also contain a file **packages.tcl**. This file will be human and machine readable. It contains a description of every core distributed package, where the sources can be found, as well as which fossil tags can be utilized as either development or release with this particular version of the core. **packages.txt** contains a series of keywords populating a data structure. A simple example would by the tclconfig templates from TEA: EXTENSION tclconfig { tag trunk fossil_url http://core.tcl.tk/tclconfig } The EXTENSION keyword is intended to take the following arguments: > _name_ _key/value-configuration-dict_ ## Reserved keys ### tag Source code management tag for the release bundled with this edition of the core ### fossil\_url If the extension is managed via fossil, a url that can be fed to "fossil clone". If no tag is specified "trunk" is assumed. ### git\_url If the extension is managed via git, a url that can be fed to "git clone". If no tag is specified "HEAD" is assumed ### file\_url If the extension is only available via source snapshot, a url where the file can be downloaded. Supported formats are .tar.gz and .zip. The list is kept separate from the actual **make.tcl** so that users can simply steal the list for making "batteries included" distributions. It also allows the package list to remain distinct for each branch of the core. # Copyright This document has been placed in the public domain. |
Name change from tip/454.tip to tip/454.md.
|
| < | < | | | | | | | | | | > | | | | | | | | < > | < > | | | | | | | | | | < > | | | | | | | < > | | | | | | | | | | | < > | | | | | | | | | | | < > | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 454: Automatically Resize Frames After Last Child Removed Author: Harald Oehlmann <[email protected]> Author: Harald Oehlmann <[email protected]> Author: Francois Vogel <[email protected]> State: Draft Type: Project Vote: Pending Created: 21-Sep-2016 Post-History: Keywords: Tk Tcl-Version: 8.6.6 ----- # Abstract A **frame**-like widget has 1x1 required size if created. If children are added by pack/grid and the last children is unpacked/grid, the frame-like widget does not return to the 1x1 required size. Instead, it keeps the size of the last packed item. It should automatically or under control resize to the initial requested size of 1x1. # Rationale A **frame** keeping a size without reason just feels like a bug and mostly leads to unwanted results. Mostly, it looks just ugly, but there are critical use-cases, specially in scrolled frames. When the BWidget autoscroll package is used, which displays scrollbars on demand, the scrollbars do not disappear if the contents is gone. And there is nothing, a programmer can do, as the Configure event does not fire on the scrolled frame widget. Another example is the scrolledwindow example by Emiliano in ticket 2863003fff <https://core.tcl.tk/tk/info/12006979562649c9> , where the solution 2 specific part may be removed \(or is ignored\). A typical workaround is to configure the width/height manually after the last children was unmapped. Unfortunately, this fact may not be determined for example by scrolling widgets etc. An eventual Configure binding is not firing. # Example Here is an example to ilustrate the issue. It consisting of a simple scrolling megawidget. The megawidget exposes a frame where a user may pack or grid other widgets and the scrollbar is adjusted following the changing content. This works well when widgets are added or removed. Only removing the last client will not update the scrollbar. With the proposed patch applied, it will update the scrollbar also when the last user widget is removed. Please paste the code below to a wish console or execute it. On startup it shows on the console: requested frame height: 1 Then press the "\+" button to add a user widget. The console output is: + requested frame height: 100 Technically, the frame ".c.f.i1" was packed into the client frame ".c.f". The client frame ".c.f" changes its requested size to hold the new child, which invokes the Convigure event and adjustes the scrolling region of the canvas. The new scrolling region is shown graphically by the scrollbar. Then press the "-" button to remove the user widget. The console output is: - So, the child widget ".c.f.i1" is destroyed, but the frame ".c.f" does not rechange its requested size to 1x1 \(initial value\) but stays at 100x100 showing an empty plane. The scrollbar is not updated and the megawidget has no possibility to adjust that \(expect additional user action to inform that the last child was removed\). One may also try to add two childs and to remove them. It gets clear, that the widget is resized on removel if it is not the last widget. With the proposed patch applied, the removal of the last widget would restore the initial frame size of 1x1 which would invoke the Configure event and the scrollbar would be adjusted. wm geometry . 90x90 # Button to add box on scrolling canvas set itemNo 0 pack [button .b1 -command newBox -text +] -side left -fill y proc newBox {} { puts + incr ::itemNo pack [frame .c.f.i$::itemNo -borderwidth 4 -relief raised -bg red -width 100 -height 100] -side top } # Button to remove box on scrolling canvas pack [button .b2 -command removeBox -text -] -side left -fill y proc removeBox {} { puts - if {$::itemNo == 0} {return} destroy .c.f.i$::itemNo incr ::itemNo -1 } # This is the scrolling megawidget which exposes frame .c.f for users to pack or grid clients # It has no knowledge, when the user adds or removes clients, e.g. when +/- is pressed pack [scrollbar .s -command {.c yview}] -side right -fill y pack [canvas .c -borderwidth 0 -yscrollcommand {.s set}] -side left -fill both frame .c.f .c create window 0 0 -window .c.f -anchor nw -tags win proc frameConfigure {} { set y [winfo reqheight .c.f] puts "requested frame height: $y" .c configure -scrollregion [list 0 0 100 $y] } frameConfigure bind .c.f <Configure> frameConfigure # Proposal The proposal is to change request size of the frame automatically to 1x1 if the last children is unpacked/ungridded/destroyed. Koen Dankart has passed a patch for this solution containing 3 additional lines of C code. It is available in branch bug-d6b95ce492-alt: <http://core.tcl.tk/tk/timeline?r=bug-d6b95ce492-alt&nd&c=2016-09-22+09%3A16%3A21&n=200> . It just solves the issue by restoring initial size if the last children is unpacked/ungridded. This is not backward compatible. But that is a side effect of fixing this bug. # Rejected Proposal Another proposal is to invoke the virtual event <<GeometryManager>> when the last children is unpacked/ungridded/destroyed. Emiliano has provided a ticket 2863003fff <https://core.tcl.tk/tk/info/2863003fff> with the implementation in branch bug-d6b95ce492 <https://core.tcl.tk/tk/timeline?r=bug-d6b95ce492&nd&c=2016-09-21+06%3A32%3A55&n=200> : The virtual event **<<GeometryManager>>** is defined which informs the master \(a frame-like widget\) that it has no child widget any more and that its size is not managed any more by grid/pack. The program may bind to this event and resize to size 1x1: bind .c <<GeometryManager>> "resizeFrame %W" proc resizeFrame w { $w configure -height 1 -width 1 $w configure -height 0 -width 0 } Discussion: * Backward compatible, no visual change to present code * Requires additional code to fix the bug \(auto-resizing to 1x1\) * The information of the last size is preserved and may be queried by the script \(winfo reqheight\) * Other sizes may be set on this event * May extend the first solution, maybe in another TIP. * May be emulated by a Configure event and some code, if the first solution is used. * Feels like a workaround to me. # Voted as yes and withdrawn due to implementation and compatibility issues The TIP was voted yes. \(only this section was added after voting\) Nevertheless, it was withdrawn due to the following compatibility issues: * flickering Moen wrote on the core list on 2016-10-26 18:53: I have to say though that I'm getting less sure about this TIP. I found some comments in the code indicating that the old behaviour was not so much a design choice, but rather an implementation issue. Specifically, this comment in tkGrid.c:1735. /* * If the master has no slaves anymore, then don't do anything at all: * just leave the master's size as-is. Otherwise there is no way to * "relinquish" control over the master so another geometry manager can * take over. */ The current patch for TIP 454 bypasses this by doing the Tk\_GeometryRequest\(\) immediately instead of at idle time. The result is that another geometry manager can still take over, but it introduces some flickering \(collapse \+ expand\): pack [text .t] pack forget .t; grid .t grid forget .t; pack .t * Additional Configure The patch introduces an additional Configure event where applications may not be aware of. Brian worte on 2016-10-26 19:46: It turns out that this "flicker" is also what is causing our tests to hang. Our UI is a complex set of nested and tabbed panes where the implementation that manages the panes relies on a complex dance of <Configure>, <Map> and <Unmap> events to make the right things happen. The consequence of adding one more <Configure> event is causing a hang at a [tkwait visibility $win] where $win never appears. $win is a single child in a frame that is unmanaged and \(re\)managed based on various conditions. The hang is easily solved, but that means that the behavior is different. \(the difference is not right or wrong, just different\*\) This difference is also demonstrated in the textWind failures. It could be asserted that these tk tests are confirming that the comment in the tkGrid.c has been faithfully implemented. I cannot write just one piece of code that works in both 8.6.6 and 8.6.7. I contend that this sort of thing is forbidden in a minor patch release, and questionable in a major patch relase \(e.g. 8.7\). I'm struggling with this, but I think this kind of change might have to be deferred to 9.0. *: the change in our code means removing some code. From a perspective of "less is more", the patch is "better". Due to those issues, the TIP is withdrawn. A way to solve the issue in a compatible and working way is to use Emilianos additional virtual event, as described in the section 'rejected alternatives'. # Additional information and examples * frame wiki page <http://wiki.tcl.tk/frame> * Tk bug ticket <https://core.tcl.tk/tk/info/d6b95ce49207c823> * Discussion on the core list <http://code.activestate.com/lists/tcl-core/16363/> # Compatibility Fixing the issue breaks visual compatibility. Nevertheless, as it is seen as a bug, this is OK. # Reference Implementation Reference implementations are mentioned in the solution sections. # Copyright This document has been placed in the public domain. |
Name change from tip/455.tip to tip/455.md.
|
| < | < | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 455: Extensions to [vwait]: Variable Sets and Scripted Access to Tcl_DoOneEvent Author: Christian Werner <[email protected]> State: Draft Type: Project Tcl-Version: 8.7 Vote: Pending Created: 07-Oct-2016 Keywords: Tcl, event loop Post-History: ----- # Abstract This TIP generalizes the **vwait** command to allow waiting on zero, one, or more variable changes, on zero or more file events, to time-limit the wait, and to control on which kinds of events is to be waited by partially exposing the underlying API, namely _Tcl\_DoOneEvent\(\)_. # Rationale One remarkable property of Tcl is the ability to add traces, i.e., the execution of callback functions, on certain operations affecting variables. The **vwait** command combines the variable trace facility with the \(a\) event loop, i.e., the \(a\) program main loop waiting and processing various types of events generated by I/O channels, time, and internal activities of the running Tcl program. The current implementation of **vwait** allows to open an unconstrained event loop which is terminated by writing or unsetting exactly one global variable given as argument to **vwait**. This proposal extends **vwait** to terminate its event loop on occurence of 1. zero or more variable modifications 2. readability/writability of zero or more file channels \(usually sockets\) 3. an optional timeout specified as milliseconds as in the **after** command. Additional flags to **vwait** control which types of events are to be dealt with in its event loop, i.e. the underlying _Tcl\_DoOneEvent\(\)_ API. When more than one kind of active input \(both, variables and file channels\) is involved in an instance of **vwait**, another flag controls if any one of the inputs or all inputs must have been activated in order to terminate the event loop. This allows for scenarios, where **vwait** can be used as a kind of "barrier" getting broken if all required conditions are fulfilled, i.e., axe, saw, spade, fire accelerant, water, in order to demolish, burn down, extinct the glow, and finally bury the trellis-work fence. However, in contrast to the illustrious demolition job, the order of occurence of events breaking that "barrier" is indeterminate. If the **vwait** is constrained by a timeout, and the time limit is reached, its event loop terminates early and **vwait** indicates that timeout by a negative integer result. Otherwise, the return value is the remaining number of milliseconds \(positive integer which can be zero\) of the timeout constraint. This property combined with [[302]](302.md) allows to implement \(soft real-time\) control loops. # Proposal The **vwait** command shall have the following signature: > **vwait** _variable-name_ - well known and implemented behaviour > **vwait** _options_ ?_variable-names_? - all available enhanced features; more than one variable name may be given, in which case the wait will terminate when any of the variables are written to \(unless the **-all** option below is given\) where _options_ are: --: indicates end of options -all: all \(except timeout\) conditions must be met -nofileevents: don't consider file events -noidleevents: don't consider idle events -notimerevents: don't consider timer events -nowindowevents: don't consider window system events -readable <chan>: _<chan>_ becomes readable -timeout <ms>: timeout in milliseconds; return the estimated number of milliseconds remaining in the wait. -writable <chan>: _<chan>_ becomes writable The return value of **vwait** shall be the empty string except when the **-timeout** option is in effect \(see above\). Where the combination of options doesn't make sense, or even conflicts, an appropriate error message shall be thrown, e.g., **-timeout** and **-notimerevents** can't be specified at the same time. If all event types except idle events are excluded, the event loop \(_Tcl\_DoOneEvent_\) shall be constrained by **TCL\_DONT\_WAIT**. Interesting analogies to the **update** command can be infered: **vwait --** is equivalent to **update**, **vwait -nofileevents -notimerevents -nowindoevents** is equivalent to **update idletasks**. # Copyright This document has been placed in the public domain. In legislations where this concept does not exist the CC0 license applies. |
Name change from tip/456.tip to tip/456.md.
|
| < | < | | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 456: Extend the C API to Support Passing Options to TCP Server Creation Author: LemonBoy <[email protected]> Author: lime boy <[email protected]> State: Final Type: Project Vote: Done Created: 18-Nov-2016 Post-History: Keywords: Tcl,socket,SO_REUSEPORT,SO_REUSEADDR Tcl-Version: 8.7 ----- # Abstract The **Tcl\_OpenTcpServer** interface doesn't provide enough flexibility as experienced during the implementation of the scaffolding necessary to support the **SO\_REUSEPORT** flag for sockets. This TIP adds that capability through a new API function, **Tcl\_OpenTcpServerEx**, that takes extra options. # Rationale Currently there's no way to pass extra informations to **Tcl\_OpenTcpServer** which is the function that does the heavy lifting by wrapping the socket creation and connection phase. For example, during the implementation of a **-reuseport** option for the **socket** command, a roadblock was hit since informing **Tcl\_OpenTcpServer** about the presence of the new flag was only possible via hacks such as exploiting the upper unused bits of the port parameter or its sign bit. A clean solution that also paves the way to the implementation of other switches \(such as one for the SO\_REUSEADDR flag\) is to introduce another function named **Tcl\_OpenTcpServerEx** whose signature closely matches the **Tcl\_OpenTcpServer** but allows passing a set of flags to customize its behaviour. Following the aforementioned changes to the C API the **socket** command is enhanced with two new options allowing the user to take advantage of the newly introduced flags. # Specification A **Tcl\_OpenTcpServerEx** function is introduced with the following signature: > Tcl\_Channel **Tcl\_OpenTcpServerEx**\(Tcl\_Interp \*_interp_, const char \* _service_, const char \*_myHost_, unsigned int _flags_, Tcl\_TcpAcceptProc \*_acceptProc_, ClientData _acceptProcData_\) Most arguments are identical to **Tcl\_OpenTcpServer** with the exception of the _port_ parameter being replaced by the _service_ one taking a string instead of an integer. Two entries for the _flags_ bitset are defined by this TIP: * **TCL\_TCPSERVER\_REUSEADDR** - indicate that the socket flag SO\_REUSEADDR \(or equivalent\) should be set. * **TCL\_TCPSERVER\_REUSEPORT** - indicate that the socket flag SO\_REUSEPORT \(or equivalent\) should be set. The **Tcl\_OpenTcpServer** function is then rewritten to be an alias of **Tcl\_OpenTcpServerEx** with the **flags** parameter set by default to TCL\_TCPSERVER\_REUSEADDR so that we keep the API and behaviour compatible with the previous Tcl versions. As for the Tcl side, the **socket** command gains two new optional switches that are only valid for server sockets: **?-reuseaddr boolean?** and **?-reuseport boolean?**, both accepting a boolean argument to either turn off or on the selected behaviour. # Reference Implementation Please refer to the _tip-456_ branch of the core Tcl repository. # Backwards Compatibility Since **Tcl\_OpenTcpServer** can be easily re-implemented in terms of **Tcl\_OpenTcpServerEx** the old behaviour is retained. The **socket** command defaults to **-reuseaddr** set to _yes_ as it was already doing before, the user is now able to turn off this behaviour by using **-reuseaddr no**. # Copyright This document has been placed in the public domain. |
Name change from tip/457.tip to tip/457.md.
|
| < | < | | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | < > | | | | | | | | | < > | < > | < > | | | | | | | | | | | | | | | < > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 | # TIP 457: Add Support for Named Arguments Author: Mathieu Lafon <[email protected]> Author: Andreas Leitgeb <[email protected]> State: Draft Type: Project Vote: Pending Created: 21-Nov-2016 Post-History: Keywords: Tcl,procedure,argument handling Tcl-Version: 8.7 ----- # Abstract This TIP proposes an enhancement of the Tcl language to support named arguments and additional features when calling a procedure. # Rationale The naming of arguments to procedures is a computer language feature which allow developers to specify the name of an argument when calling a function. This is especially useful when dealing with arguments with default values, as this does not require to specify all previous arguments when only one argument is required to be specified. As such, this is a commonly requested feature by Tcl developers, who have created various code snippets <http://wiki.tcl.tk/10702> to simulate it. These snippets have drawbacks: not intuitive for new users, require to add extra code at the start of each procedure, no standard on the format to use, few errors handling, etc. After discussing various possibilities with the community, it has been decided to extend the argument specification of the _proc_ command and allow users to define options on arguments. This can be used to support named arguments but also add additional enhancements: flag arguments, pass-by-name \(_upvar_\) arguments, non-required arguments, ... The others possibilities discussed are detailed in the _Discussion_ section at the end of the document. # Specification The _proc_ documentation currently define argument specifiers as a list of one or two fields where the first field is the name of the argument and the optional second field is its default value. The proposed modification is to support an alternate specifier format where the first field is also the name of the argument, followed by a paired list of options and their values. This format does not prevent the original format to be used as they can be easily distinguished: the new format uses an odd size list with a minimal size of three fields. ## Available argument specifiers The following argument specifiers are defined in this TIP: * **-default VALUE** defines the default value for the argument. It is ignored if _-required 1_ is also used. % proc p { { a -default {} } } { list a $a } % p a {} % p foo a foo * **-name NAME** defines the argument to be a named argument. NAME defines the name of the argument when it is defined as a single string. If NAME is a list of strings, it is the list of names that can be used to refer to the argument \(i.e. aliases\). On the call-site, the name of the argument is prefixed by a single dash and followed by the value. % proc p1 { { v -name val } } { list v $v } % p1 -val 1 v 1 % proc p2 { { v -name {v val value} } } { list v $v } % p2 -value 2 v 2 % p2 -v 2 v 2 * **-switch SWITCHES** defines that the argument is defined on the call-site as a flag-only/switch parameter. SWITCHES is a list of possible switches. Each switch is defined either as a single string \(switch name\) or as a list of two entries \(switch name and related value\). On the call-site, the name of the switch is prefixed by a single dash and is not followed by any value. The value assigned to the argument is either the switch name or the related value depending on how it was defined. % proc p { { dbg -default 0 -switch debug } } { list dbg $dbg } % p dbg 0 % p -debug dbg debug % proc p { { level -switch {{quiet 0} {verbose 9}} } { list level $level } % p -quiet level 0 % p -verbose level 9 * **-required BOOLEAN** defines that the value is required to be set. If set to true, the argument is required and any default value is ignored. It is the default handling for non-named argument without a default value. If set to false, the argument is not required to be set and the related argument will be left unset if there is no default value. It is the default handling for named argument. % proc p { { v -required 0 } } { if {[info exist v]} {list v $v} {return "v is unset"} } % p 5 v 5 % p v is unset * **-upvar LEVEL** defines, that the local argument will become an alias to the variable in the frame at level LEVEL corresponding to the parameter value. This is similar to what is achieved when using the _upvar_ command. This specifier is incompatible with the _-switch_ specifier. % proc p { { v -upvar 1 } } { incr v } % set a 2 2 % p a 3 % set a 3 Further argument specifiers may be added in future TIP. Examples of new argument specifiers which may be added in the future: * type assertion \(**-assume TYPE**\) * argument documentation \(**-docstring DOC**\) * ... ## Named arguments The following rules define how named arguments are expected to be specified on the call-site: * Named arguments must always be specified using their name, they can't be specified as positional arguments. % proc p { {a -name A} } { list a $a } % p aa wrong # args: should be "p |-A a|" % p -A aa a aa * When several names \(using _-name_ or _-switch_ options\) are specified for the same argument, only one is required to be used on the call-site, unless a default value is also specified. If more than one is used, the latest value/switch is kept. % proc p { { v -name {v val} } } { list v $v } % p -v 6 -val 8 v 8 * Both _-name_ and _-switch_ specifiers can be used on the same argument. % proc p { { level -name level -switch {{quiet 0} {verbose 9}} } { list level $level } % p -level 4 level 4 % p -verbose level 9 * A group of contiguous named arguments are handled together and are not required to be specified in the same order as defined. % proc p { {a -name A} {b -name B} } { list a $a b $b } % p -B bb -A aa % a aa b bb * The handling of a group of contiguous named arguments \(which can be only one argument\) is ended on the first argument which is either a parameter not starting with a dash or the special _--_ end-of-options marker. Remaining arguments will then be assigned to following positional arguments. % proc p { {o -name opt} args } { list o $o args $args } % p -opt O 5 o O args 5 % p -opt O -1 0 wrong # args: should be "p |-opt o| ?arg ...?" % p -opt O -- -1 0 o O args {-1 0} * If there is a fixed number of non-optional positional arguments and no special _args_ variable after the named group, the handling of a named group will also be ended when the remaining arguments to assign will be equal to the number of positional arguments after the group. % proc p { {o -name opt} posarg } { list o $o posarg $posarg } % p -opt O -1 o O posarg -1 ## Generated usage description The error message, automatically generated when the input arguments are invalid, is updated regarding new options: * Pass-by-name arguments \(specified using _-upvar level_ option\) are surrounded by the '&' character. % proc p { { v -upvar 1 } } { } % p wrong # args: should be "p &v&" * Named arguments are showed how they should be called and surounded by the '\|' character. If several names have been specified, they are grouped together. % proc p { { l -name level -switch {high low} -required 1} } {} % p wrong # args: should be "p |-level l|-high|-low|" * When an argument is optional, '?' is used. % proc p { { v -name var } a } {} % p wrong # args: should be "p ?|-var v|? a" ## Introspection The _info argspec proc_ command is added to get the argument specification of all arguments or of a specific argument. % proc p { a { b 1 } { c -name c } } {} % info argspec proc p a { b -default 1 } { c -name c } % info argspec proc p c -name c Similar _info argspec_ subcommands are also added for lambda, object method and object constructor. The _info argspec specifiers_ command is added to get the specifiers supported by the current interpreter. % info argspec specifiers -default -name -required -switch -upvar ## Other use cases Extended argument specifiers can also be used with other _proc_-like functions. The following functions are supported and can use extended argument specifiers: * anonymous functions \(lambda\), used with _apply_ command ; * TclOO constructor or methods. ## Performance The proposed modification has no significant performance impact: * existing code \(and code not using extended argspec\) is not impacted by the change as the current initialisation code is still available and used ; * code using extended argspec _may_ be impacted because the initialisation code is different and is required to loop on each argument, but initial testing does not show a significant slowdown. When using named arguments specifiers to replace a similar handling done in Tcl-pure code, there is however a significant increase in performance. See <https://gist.github.com/mlafon/70480877a28f3571e0377eabc0cee7be> for details on performance testing done on the proposed implementation. # Implementation This document proposes the following changes to the Tcl core: 1. Add ExtendedArgSpec structure which is linked from CompiledLocal and contains information about extended argument specification; 2. Add a flags field in the Proc structure to later identify a proc with at least one argument defined with an extended argument specification \(PROC\_HAS\_EXT\_ARG\_SPEC\); 3. Update proc creation to handle the extended argument specification and fill the ExtendedArgSpec structure; 4. Update InitArgsAndLocals to initialize the compiled locals using a dedicated function if the PROC\_HAS\_EXT\_ARG\_SPEC flag has been set on the proc. If unset, the original initialization code is still used. 5. Update ProcWrongNumArgs to generate an appropriate error message when an argument has been defined using an extended argument specification; 6. Add _info argspec_ command; 7. Update documentation in doc/proc.n and doc/info.n; 8. Update impacted tests and add dedicated tests in tests/proc-enh.test. ## Reference Implementation The reference implementation is available in the tip-457 <http://core.tcl.tk/tcl/timeline?r=tip-457> branch. The code is licensed under the BSD license. # Discussion This section details some of the alternate solutions for this feature or specific comments about it. Initial approaches that tried to work with unmodified procedures are not detailed here for clarity. ## Dedicated builtin command A dedicated command can be used to handle the named arguments, using an _-option value_ syntax, before calling the target procedures with all arguments correctly prepared. % call -opts myproc -optC foo -optB {5 5} -- "some pos arg" An implementation of this proposal is available at <https://github.com/mlafon/tcl/tree/457-CALL-CMD> . This proposal was abandoned as it was not enough intuitive for users. ## Modification in how proc are defined Tcl-pure procedures can be defined in a way which state that the procedure will automatically handle _-option value_ arguments. % proc -np myproc { varA { optB defB } { optC defC } { optD defD } args } { .. } % myproc -optC foo -optB {5 5} -- "some pos arg" An other possibility is to support options on arguments and allow name specification: % proc myproc { varA { optB -default defB -name B } args } { .. } % myproc a -B b zz This is the currently proposed solution in this TIP. It requires the procedures to be modified but allow additional features. Some people have expressed concern about the modification of the _proc_ command, which is a core command of Tcl. A particular attention has been paid to ensure that existing code will not be impacted and that future usage could be later added by adding new specifiers. ## Argument Parsing command Cyan Ogilvie's paper from Tcl2016 <https://www.tcl.tk/community/tcl2016/assets/talk33/parse_args-paper.pdf> describes a C extension to provide core-like argument parsing at speed comparable to _proc_ argument handling, in a terse and self-documenting way. Alexandre Ferrieux has proposed <http://code.activestate.com/lists/tcl-core/18447/> to use the same argument specifiers than this proposal, but with a dedicated command which can be called from the proc body. This has the advantage to not alter the _proc_ command and could be located in an extension. Although the _proc_ usage will not be modified, this new command will probably have to access or modify internal proc structures, for example to support introspection. Having to declare final local variables in the body, also seems confusing for users. ## Preventing Data-dependent bugs It has been proposed by Christian Gollwitzer <http://code.activestate.com/lists/tcl-core/18457/> to make the special '--' end-of-options marker mandatory when the number of positional arguments after the named group is not fixed. This would suppress any potential Data-Dependent bugs related to the search of the initial dash and remove any unwanted object stringification, at the expense of forcing the user to explicitely use the end-of-option marker. This proposal is currently not implemented but the documentation has been modified to list the cases for which '--' should be use. # Copyright This document has been placed in the public domain. |
Name change from tip/458.tip to tip/458.md.
|
| < | < | | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 458: Add Support for epoll() and kqueue() in the Notifier Author: Lucio Andrés Illanes Albornoz <[email protected]> Author: Lucio Andrés Illanes Albornoz <[email protected]> State: Final Type: Project Vote: Done Created: 24-Nov-2016 Post-History: Keywords: event loop,scalability Tcl-Version: 8.7 ----- # Abstract This TIP proposes to replace _select_\(2\) in the notifier implementation with _epoll_\(7\) and _kqueue_\(2\) on Linux and DragonFly-, Free-, Net-, and OpenBSD respectively. This is to remove a major bottleneck in the ability of Tcl to scale up to thousands and tens of thousands of sockets \(aka **C10K**\). Furthermore, this should also provide sufficient infrastructure in order to permit adding support for other platform-specific event mechanisms in the future, such as IOCPs on Solaris and Windows. # Rationale The drawbacks associated with _poll_\(2\) and _select_\(2\) and the tremendously improved ability to scale of _epoll_\(7\) and _kqueue_\(2\) are well-known <https://en.wikipedia.org/wiki/C10k_problem> ; a previous attempt at implementing this feature elaborates on this subject and can be found at <https://sourceforge.net/p/tcl/mailman/tcl-core/?viewmonth=200909&viewday=10> . Initially, the notifier thread was retained to provide for event notification and inter-thread IPC. This eventually proved unnecessary and thus the _epoll_\(7\)/_kqueue_\(2\) source modules now no longer contain the notifier thread and its infrastructure, particularly as this also reduces code size and complexity. Threads that intend to wait on one or more file descriptors they own will now directly call _epoll\_wait_\(2\)/_kevent_\(2\) themselves during _Tcl\_WaitForEvent_\(\). Inter-thread IPC is provided for by a per-thread trigger pipe, analogous to the trigger pipe of the notifier thread. On Linux, an _eventfd_\(2\) is used instead, which only requires one single fd. Furthermore, events for regular files are not processed via _epoll_\(7\), as it does not support them at present. Instead, events for regular files are immediately returned by the notifier when waiting for events. The new implementation of the notifier only has two minor drawbacks: 1. Each thread that has called _Tcl\_WaitForEvent_\(\) at least once will create an _epoll_\(7\)/_kqueue_\(2\) file descriptor. 2. All threads create two _pipe_\(2\) file descriptors for inter-thread IPC; on Linux, one single _eventfd_\(2\) is created and used. Therefore, threads that have waited on events at least once now own an additional amount of three/two file descriptors. Whether this could prove to be a problem remains a point of contention that should be subject to further discussion. As far as the notifier implementation is concerned, threads do not share data structures or file descriptors; IPC is provided for explicitly. However, a thread may queue events to and then alert another thread in order to allow for less primitive forms of IPC. Therefore, the previously static mutex protecting the notifier list has become a per-thread mutex. Instead of protecting the notifier list, it protects per-thread event queues from event queue/unqueue race conditions. This only applies to the _epoll_\(7\)/_kqueue_\(2\)-based notifier implementations. The majority of Tcl code should be unable to observe any difference at the script level. # Specification At present, code changes are almost entirely constrained to either _unix/tclEpollNotfy.c_ wherever _epoll_\(7\) is supported or _unix/tclKqueueNotfy.c_ wherever _kqueue_\(2\) is supported. The original _select_\(2\)-based notifier implementation now lives in _unix/tclSelectNotfy.c_. Subroutines shared between _unix/tcl\{Epoll,Kqueue\}Notfy.c_ have been moved to _unix/tclUnixNotfy.c_, which is **\#include**d by the former. As explained in the last section of this document, the previously static mutex in _generic/tclNotify.c_ has become a per-thread mutex. The new code associates the newly introduced \(but private\) _PlatformEventData_ structure with each file descriptor to wait on and its corresponding _FileHandler_ struct. _PlatformEventData_ contains: 1. A pointer to the _FileHandler_ the file descriptor belongs to. This specifically facilitates updating the platform-specific mask of new events for the file descriptor of a _FileHandler_ after returning from _epoll\_wait_\(2\)/_kevent_\(2\) in _NotifierThreadProc_\(\). 2. A pointer to the _ThreadSpecificData_ of the thread to whom the _FileHandler_ belongs. This specifically facilitates alerting threads waiting on one or more _FileHandlers_ in _NotifierThreadProc_\(\). The core implementation is found in a set of six \(6\) newly introduced static subroutines in _unix/tcl\{Epoll,Kqueue\}Notfy.c_: 1. _PlatformEventsControl_\(\) - abstracts _epoll\_ctl_\(2\)/_kevent_\(2\). Called by _Tcl\_\{Create,Delete\}FileHandler_\(\) to add/update event masks for a new or an old _FileHandler_ and _NotifierThreadProc_\(\) in order to include the _receivePipe_ fd when waiting for and processing events. 2. _PlatformEventsFinalize_\(\) - abstracts _close_\(2\) and _ckfree_\(\). Called by _Tcl\_FinalizeNotifier_\(\). 3. _PlatformEventsGet_\(\) - abstracts iterating over an array of events. Called by _NotifierThreadProc_\(\). 4. _PlatformEventsInit_\(\) - abstracts _epoll\_create_\(2\)/_kqueue_\(2\). Called by _PlatformEvents\{Control,Wait\}_\(\) and _Tcl\_WaitForEvent_\(\). 5. _PlatformEventsTranslate_\(\) - translates platform-specific event masks to **TCL\_\{READABLE,WRITABLE,EXCEPTION\}** bits. Called by _Tcl\_WaitForEvent_\(\). 6. _PlatformEventsWait_\(\) - abstracts _epoll\_wait_\(2\)/_kevent_\(2\). Called by _Tcl\_WaitForEvent_\(\) and _NotifierThreadProc_\(\). Two additional subroutine are used in all three code paths \(_epoll_, _kqueue_, _select_\) to reduce code redundancy: 1. _AlertSingleThread_\(\) - notify a single thread that is waiting on I/O. Called by _NotifierThreadProc_\(\). 2. _TclUnixWaitForFile\(\) - reimplemented via _poll_\(2\) instead of _select_\(2\), as _poll_\(2\) does not suffer the **FD\_SETSIZE** limit on file descriptors that can be passed to _select_\(2\) and is available on a sufficiently large number of platforms. Most importantly, this code would not benefit from using _epoll_\(7\) or _kqueue_\(2\) as this subroutine only waits on one single file descriptor at a time. _PlatformEventsInit_\(\) currently defaults to allocating space for 128 array members of _struct epoll\_event/kevent_. This could preferably be handled through e.g. _fconfigure_. Originally, a mutex used to protect the _epoll_\(7\)/_kqueue_\(2\) file descriptor and the above mentioned array. This proved to be redundant as _epoll\_ctl_\(2\) can be called whilst blocking on _epoll\_wait_\(2\) on Linux and as _kevent_\(2\) can be called whilst blocking on _kevent_\(2\) on FreeBSD. Lastly, the _configure_ script is updated to define **HAVE\_EPOLL** or **HAVE\_KQUEUE** as appropriate. # Reference implementation Please refer to the _tip-458_ branch. The code is licensed under the BSD license. # Copyright This document has been placed in the public domain. In legislations where this concept does not exist the BSD license applies. |
Name change from tip/459.tip to tip/459.md.
|
| < | < | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 459: Tcl Package Introspection Improvements Author: Jan Nijtmans <[email protected]> State: Draft Type: Project Vote: Pending Created: 08-Dec-2016 Post-History: Keywords: Tcl,package Tcl-Version: 8.7 ----- # Abstract This TIP proposes to improve package introspection by providing a new command **package files**. # Rationale This TIP is inspired by a request from FlightAware to improve Tcl's package introspection possibilities. Although only a **package files** command was requested, extending **info loaded** gives the possibility to find a shared library contained in a package more easily than searching a list. # Specification of the proposed Change Two new additions are proposed, to the **package** and **info** commands. 1. **package files** _name_ > This command returns a list of filenames which were sourced during the initialization of package _name_. More specific, the files that were sourced during running the script registered using **package ifneeded**. Left out are Tcl's own tclIndex and pkgIndex.tcl files, which might have been accessed due to dependancy searches, otherwise this would give very misleading results. 1. **info loaded** ?_interpreter_? ?_name_? > The **info loaded** command already exists, it gives a list of package names with corresponding shared library names which were actually loaded in the give interpreter. The additional _name_ argument restricts the result to the filename of the loaded library only. Tcl packages don't have to do anything special in order to be introspected correctly, just note that files containing auto\_loaded commands cannot be introspected because they are not sourced during package initialization. # Rejected alternatives > Use of _source -nopkg_ in tclIndex files. Even though this addition in the earlier TIP was explicitly undocumented, it lead to the misunderstanding that other Tcl extensions should do the same. > Earlier implementation of this TIP didn't handle the second argument of **info loaded** correctly in all cases, and the handling in safe interpreters was not complete. This is all corrected in the current implementation. > All filenames should be converted to absolute. This is rejected for performance and for practical reasons. It could be quite expensive to calculate because the disk has to be accessed for possible hyper-links. Second, the package mechanism is already designed such that all sourced paths are absolute \(see below example\). Extensions using the **source** command with relative paths are in danger already, this should be fixed in the extension in stead of being masked in the **package files** command. > Additional information about the sourced files \(like mtime or checksum\) was suggested to be part of the introspection information, but this has been rejected as overkill. It is much more than requested in the Tcl-bounty, and it is difficult to imagine what actual use this would bring. # Reference Implementation This is available in the _package\_files_ branch <http://core.tcl.tk/tcl/timeline?r=package_files> . # Examples $ tclsh8.7 % package files Tcl /usr/lib/tcl8.7/init.tcl % package require Tk 8.7a0 % package files msgcat /usr/lib/tcl8/8.5/msgcat-1.6.0.tm % package files Tk /usr/lib/tk8.7/tk.tcl /usr/lib/tk8.7/msgs/en.msg /usr/lib/tk8.7/icons.tcl ... % info loaded {} Tk /usr/lib/libtk8.7.so Note that **package require Tk** has the side-effect of loading the _msgcat_ package, which is required by Tk. # Copyright This document has been placed in the public domain. Please note that any correspondence to the author concerning this TIP is considered in the public domain unless otherwise specifically requested by the individual\(s\) authoring said correspondence. This is to allow information about the TIP to be placed in a public forum for discussion. |
Name change from tip/46.tip to tip/46.md.
|
| < | < | | | | | | | > | | | | | | | | | | | | | > | 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 | # TIP 46: Consistent Overlap Behavior of Area-Defining Canvas Items Author: Gerhard Hintermayer <[email protected]> State: Withdrawn Type: Project Vote: Pending Created: 18-Jul-2001 Post-History: Tcl-Version: 8.5 ----- # Abstract This document proposes that all canvas items that define an area should behave the same in terms of interior points, i.e. points that return the enclosing object id when submitted to _[$canvas find overlapping]_. Currently polygons behave differently from the rest \(rectangle, arc, oval\). # Rationale As long as these area-defining canvas items are filled, there's no problem. The interior points belong to the object. But when the object is not filled \(i.e. -fill "" is used\), only polygons consider inside points as overlapping. For the rest of the area-defining canvas items, an interior point is _not_ considered to overlap the object. This makes it impossible to * define invisible or not filled mouse sensitive areas other than polygons because moving the pointer inside of an arc/oval/rectangle creates both an _<Enter>_ and a _<Leave>_ event, even though the pointer is still inside the item. * do object-oriented selection on a canvas. Consider you want to select a \(not filled\) oval, you _have to_ click on the vertice, or else you won't find a overlapping item. Well, I see the point, that this proposal might break existing code, but from the number of replies to my postings at news:comp.lang.tcl , _[$canvas find overlapping]_ is not used very often. One possibility to fix the backward compatibility is to introduce 2 different fill colors for the 2 cases - object either hollow or solid but not filled. Then inside points would not overlap hollow objects, but would overlap solid objects. # Proposal We should either choose a wire frame model or an object-oriented model for canvas objects. To my mind an object-oriented approach is better. Right now we have a mixture of both. Polygons are objects, arcs, ovals and rectangles are wire frames. What I'd like is: all points which are inside of an area object should return the enclosing object when passed to find overlap, _regardless_ of the fill color of the item. # Notice of Withdrawal This TIP was Withdrawn by the TIP Editor following discussion on the tcl-core mailing list. The following is a summary of reasons for withdrawal: > This would remove useful behaviour that is used rather more often than people think. If people want unfilled polygons with the other style of overlap behaviour, they should use lines. # Copyright This document has been placed in the public domain. |
Name change from tip/460.tip to tip/460.md.
|
| < | < | | | | | | | | > | | | | | | | | | | | | | | | | | | < > | | | | < > | | | < > | | | | < > | | | < > | | < > | | | | | | | | | | | | | | | | | | | | | | | < | | > | | | | | < | > | | | < | > | | | | | | | | | | | | < > | | | | < | > | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 460: An Alternative to Upvar Author: Don Hathway <[email protected]> State: Draft Type: Project Vote: Pending Created: 08-Dec-2016 Post-History: Keywords: Tcl,variable,link,upvar Tcl-Version: 9.0 ----- # Abstract Variable linking with the _upvar_ command is not as intuitive or effecient as it should be. This TIP proposes an alternative through automatic variable linking. # Rationale The current strategy used to link a variable in a called procedure to the caller, is to pass the name of the variable to the procedure, and use the _upvar_ command to create a new variable, which is then linked to the original. Thus linking to a variable requires two components; the variable name and a newly created variable. It is possible to instruct Tcl to do this linking automatically in an idiomatic way and dispense with the _upvar_ command call. Also, the requirement \(by _upvar_\) that the name of the new link variable be a different name from the original is arguably considered counter-intuitive. Benefits to this TIP as proposed: 1. **No code to perform explicit linking within the procedure's body.** Unlike _upvar_, this method requires no additional code to be entered in the body of the procedure. Less code, less bugs, easier to use! It has been said that Tcl'ers should make more use of variable linking in their code. Making it easier for them should have an encouraging effect, similar to how most Tcl'ers prefer _$var_ over _set var_. 2. **Clearly defines links in the procedure's parameter list.** Readers should instantly know what the links are. Clarity is important, especially for people that read code all day. There are no special project naming conventions to follow. A reader doesn't have to rely on docs or assume that a parameter name of "varName", "\_var", or "varLnk" is to be linked by an upvar call, of which may be pushed down in the procedure's body by comments or other code. 3. **Alleviates arguably messy _upvar_ chain linking.** ## Upvar Chaining Example Below are three _upvar_s with the same arguments. As you can see, there is quite a bit of arguably unnecessary code duplication, and that is bug prone. proc foo {a} { upvar 1 $a la maybe do something with la bar la } proc bar {a} { upvar 1 $a la maybe do something with la baz la } proc baz {a} { upvar 1 $a la maybe do something with la } foo begin This could be written more succinctly: proc foo {*a} { maybe do something with a bar a } proc bar {*a} { maybe do something with a baz a } proc baz {*a} { maybe do something with a } foo begin # Specification Add support to procedure handling to allow for a parametric hint to procedure definitions with respect to the intent to link variables accordingly. We use the asterisk character "**\***" as the symbol to declare this intent; which shall prefix the parameter's name. Consequently, the "**\***" character becomes special, but only inside the procedure parameter list. A procedure definition using this facility would then have the signature: proc foo {*a *b} {...} Where **\*a** and **\*b** are the procedure's parameters to be linked to the caller's arguments. New variables are then created for the future linking. In this example **\*a** creates a new link variable named **a**, and likewise done for **\*b**. **\*a** and **\*b** holds the values passed in by the caller. The formal parameter's shall retain the same values provided by the caller. The link variable's name shall always have one **\*** symbol less than its counterpart parameter, for the sake of consistency. In example, a parameter named **\*\*\*a** shall have a counterpart link variable named **\*\*a**. Similarily **\*\*a** shall have a counterpart link named **\*a**. Where there are duplicate link parameter names \(i.e. proc P \{\*a \*a\}\) the behavior shall be the same as if there were duplicate **upvar** statements. It is legal to have empty link variable names. It shall be possible with a single **\*** in the procedure's parameter list \(i.e. proc P \{\*\} \{incr ""\}\). The same duplicate name rule applies. If the variable to be linked does not exist, it shall be created, if necessary. It shall have the same behavior as **upvar 1** in such instances. When a link's construction fails, the behavior shall be the same as if **upvar** had failed, the procedure will return with an error before any other commands \(with exception to any commands involved in the link's construction\) in its body are executed. It is illegal for a link parameter to have a default value. It shall invoke an error during procedure creation time and result in failed procedure creation with the error code: Tcl_SetErrorCode(interp, "TCL", "OPERATION", "PROC","FORMALARGUMENTFORMAT", NULL); An example of such an error for: proc P {{*a foo}} {...} Would be: "procedure "P": formal parameter "\*a" is to be linked and must not have a default value" In that example, proc **P** is never created, the attempt failed due to the error. It is the caller's responsibility to provide the names of variables to be linked. This constraint exists in the spirit of promoting good coding practices and to help avoid obscure and subtle bugs. For the same reasons, this TIP only searches one level up. Therefore, It shall have the same behavior as **upvar 1**. **\*args** is a valid parameter name. For example, **args** is simply a link in: proc foo {a *args} { incr args } Note that as of this TIP _proc foo \{args args\} \{...\}_ is legal Tcl. In this instance only the first _scalar_ **args** is usable by the procedure. The rest of the arguments are inaccessible by the script. They're not internally lost, but Tcl's variable lookup mechanics will choose whichever is found first when a script references it. This behavior is inherited for _proc foo \{\*args args\} \{...\}_. Where **args** will be a link. To further illustrate this proposal with an example: proc foo {*a *b} { bar a b } proc bar {*a *b} { incr a incr b } set v1 0 set v2 1 foo v1 v2 puts $v1 # prints 1 puts $v2 # prints 2 # Version of foo using upvar: proc foo {a b} { # Note, upvar $a a would be an error. upvar 1 $a la $b lb bar la lb } proc bar {a b} { upvar 1 $a la $b lb incr la incr lb } The "**\***" character was chosen primarily because it resembles a star or a snowflake and has a pleasantry to it. It is one of the few ascii characters that **sticks out** from its surrounding text. It is also familiar to users of other languages where the same symbol exhibits similar semantics \(to wit: a link in Tcl acts as a reference to another variable and doesn't perform a copy when the reference is written to, as it would if it weren't a link\). However, unlike other languages, the Tcl core does not expose operations to user scripts that work directly on memory, so the "**\***" character should not be mistaken to behave the same or suffer from the same pitfalls as it does in C, C\+\+, Golang, etc. The **\*** symbol simply instructs Tcl to create a link if it is able to do so. ## Consequences 1. Breaks scripts using the special "**\***" as the first character in their procedure's parameters \(i.e. **\*var**\). > The impact of this should be minimal because these variable names require the user to wrap it in curly braces \(i.e. **$\{\*var\}**\) to fetch their values, unless they're using the less common form of **set varname**. # Reference Implementation See branch _dah-proc-arg-upvar_ ## Implementation Notes tclInt.h: Add a new field named _numArgsCompiledLocals_ to the Proc struct. The new field holds the number of parameters along with any other relevant local variables which follow immediately after the parameters. For this TIP, these additional locals are variables with the VAR\_LINK flag and to be resolved as links to the values of arguments they've been configured to link with. The additional field was a hard choice, but is necessary because _TclProcCompileProc_ enforces _procPtr->numCompiledLocals_ to be the same value as _procPtr->numArgs_. The local variable table is evidently not growable until later. tclProc.c: Modify _InitArgsAndLocals_ to do the automatic linking. Note that this is a _very hot_ function and that was kept in mind while making the necessary adjustments. There are two additional branches in the function \(the second only visited when an error happens\). The first to check if the command has any parameters that need linking and if so, process them with link support handling code. The second branch is to simply check if the link handling code set an error when an error occurs, so this branch should not be a concern as to performance impact. Due to branch prediction and this function being so hot, there should be virtually nil of a performance impact on any code which doesn't make use of the new automatic linking facility. tclProc.c: Modify _TclCreateProc_ to add additional locals after the list of parameter locals \(if any\) when there are parameters flagged for auto linking. # Copyright This document has been placed in the public domain. |
Name change from tip/461.tip to tip/461.md.
|
| < | < | | | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | < | > | | | | | | | | | | | | | | | > | 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 | # TIP 461: Separate Numeric and String Comparison Operators Author: Kevin B Kenny <[email protected]> Author: Kevin B Kenny <[email protected]> Author: Kevin Kenny <[email protected]> State: Draft Type: Project Vote: Pending Created: 24-Jan-2017 Post-History: Keywords: Tcl,expression Tcl-Version: 8.7 ----- # Abstract This TIP proposes to complete the separation between string and numeric comparison operations in [expr] and related commands \([for], [if], [while], etc.\). It introduces new comparison operators **ge**, **gt**, **le**, and **lt**, \(along with the corresponding commands in the **::tcl::mathop** namespace\), and encourages programmers to restrict the six operators **==**, **>=**, **>**, **<=**, **<** and **!=** to comparisons of numeric values. # Rationale Tcl throughout its history has had comparison operators that freely compare numeric and string values. These operators behave as expected if both their arguments are numeric: they compare values on the real number line. Hence, 15 < 0x10 < 0b10001. Similarly, if presented with non-numeric strings, they compare the strings in lexicographic order, as a programmer might expect: "bambam" < "barney" < "betty" < "fred". Trouble arises, however, when numeric and non-numeric strings are compared. The rule for comparison is that mixed-type comparisons like this are treated as string comparisons. The result is that **<** does not induce an order. There are inconsistent comparison results, rendering **<** and friends worthless for sorting. 0x10 < 0y < 1 < 0x10. The problems with this inconsistency prompted changes in May of 2000, introducing **eq** and **ne** operators that always perform string comparison. For whatever reason, the four inequality operations never followed. This leads to pitfalls for the unwary. It's fairly well entrenched in the Tcl folklore that comparisons other than **eq** and **ne** should be reserved for numeric arguments only, and experienced Tcl programmers know to write: if {[string compare $x $y] < 0} { ... } in place of if {$x < $y} { ... } # Proposal Four new bareword operators, **ge**, **gt**, **le** and **lt** shall be added to the expression parser and to the **::tcl::mathop** command set. They will have precedence identical to the existing operators **>=**, **>**, **<=** and **<**. They will accept string values, and return 0 or 1 according to lexicographic string comparison of their operators. This change is entirely backward compatible \(it uses syntax that would previously have been erroneous\), and should go in as soon as possible - no later than the next point release, but ideally even in a patchlevel - so that programmers can begin conversion as soon as possible. Use of the **==**, **>=**, **>**, **<=**, **<**, and **!=** for comparing non-numeric values shall immediately be deprecated. The six string compare operators shall be declared to function so that their results are the same as the results of [string compare]: {$a lt $b} <=> {[string compare $a $b] < 0} {$a le $b} <=> {[string compare $a $b] <= 0} {$a eq $b} <=> {[string compare $a $b] == 0} {$a ne $b} <=> {[string compare $a $b] != 0} {$a gt $b} <=> {[string compare $a $b] > 0} {$a ge $b} <=> {[string compare $a $b] >= 0} It is also intended that any future changes to [string compare] \(for example, a hypothetical change to make it follow Unicode collation semantics\) will have the corresponding effect on these six operators. Unlike what was specified in an earlier version of this TIP, no changes are to be made to the semantics of the comparison operators **==**, **>=**, **>**, **<=**, **<**, and **!=**. # Discussion ## Forcing typed comparisons in Tcl Programmers who wish to insure string semantics should restrict their comparisons to the **lt**, **le**, **eq**, **ne**, **gt** and **ge** operators. Use of the **<**, **<=**, **==**, **!=**, **>** and **>=** operators with operands that might be non-numeric shall be regarded as poor programming style. Unless operands are constant, unary **\+** should be used to force them to be numeric. Thus, if {$x < $y} { ... } should be relaced with if {+$x < +$y} { ... } The second comparison will have the effect of forcing both operands to be numeric. ## Rejected alternatives Earlier, the radical suggestion of _requiring_ the **<**, **<=**, **==**, **!=**, **>** and **>=** operators to have numeric arguments had been read into this TIP. It appears that there is far too much outstanding code that is written like: if \{$x == "somestring"\} \{ ... \} to have the more radical option be viable. One possible alternative to excluding non-numeric arguments from the comparison operators is to change their semantics so that all non-numeric strings are greater than all numbers. This change would at least yield a consistent ordering. The ordering that it yields would, however, be somewhat surprising, and not terribly useful. \(It would at least be compatible with today's scheme for numeric comparisons.\) ## Objections \(and rebuttals\) In out-of-band discussions, several objections were raised. This section attempts to address them. 1. _Tcl's expression parser has a hard limit of 64 different binary operators. This proposal consumes four of them, leaving only 28. There is a concern that this is a less-than-effective use of a limited resource._ > The limit is self-imposed, in an effort to make the nodes of an expression parse tree fit in exactly 16 bytes \(or four int's\). It is far from obvious that this pretty size is actually useful. Few expressions are more than a few dozen parse nodes, and typical expressions are not parsed multiple times. It appears that neither the speed of the parse nor the size of the tree will be critical issues in most applications. In any case, we still have nearly half the operators left. 2. _There is some concern that using barewords for operators was a bad idea in the first place._ The fact that expr {"foo"} > and set x foo; expr {$x} > both work, while expr {foo} > is an invalid bareword is arguably surprising. > Nevertheless, we have committed to the approach with the **eq**, **ne**, **in** and **ni** operators. These are unlikely to go away. Adding **lt**, **le**, **gt** and **ge** will make this problem no better nor worse. > Moreover, the language of [expr] is not the same as Tcl. It does not strip comments, parse into words, and apply Tcl's precise substitution rules - and it would be surprising if it did! There are other "little languages" throughout Tcl - regular expressions, glob patterns, assembly code, and so on. [expr] is one among many. 3. _There is concern that [expr], which was originally intended almost exclusively for numeric calculations, is being abused with string arguments and possibly string results._ > The author of this TIP contends that we introduced string values to [expr] a long time ago, certainly by the time that the **eq**, **ne**, **in** and **ni** operations were introduced. It is true that the use of numeric conversions in [expr] is incoherent, as seen in: % proc tcl::mathfunc::cat {args} { join $args {} } % expr {cat(0x1,0x2,"a")} 0x10x2a % expr {cat(0x1)} 1 > \(Bug [e7c21ed678] is another manifestation of this general problem.\) Once again, adding additional string operations that behave, with respect to data types, exactly the same as ones that are already there will neither fix nor exacerbate the general problem. 4. _Because [expr] has no interpreted form, the operations must have bytecode representations. The space of available bytecodes is under even more pressure than the space of available operators, and must not be squandered on operations that are duplicative of already-available functionality such as [string compare]._ > The obvious rebuttal is that [string compare] is already bytecoded. There are no new operations required, merely a compiler that is smart enough to emit a short codeburst rather than a single bytecode. As an example, the code for the expression {$x lt $y} > could be: (0) loadScalar1 %v0 # var "x" (2) loadScalar1 %v1 # var "y" (4) strcmp (5) push1 0 # "0" (7) lt > For the other string operators, only the last bytecode in the burst would change. No new bytecode operations are needed. In fact, this codeburst is identical code to that generated for the expression {[string compare $x $y] < 0} # Copyright This document has been placed in the public domain. |
Name change from tip/462.tip to tip/462.md.
|
| < | < | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 462: Add New [info ps] Ensemble for Subprocess Management Author: Frédéric Bonnet <[email protected]> State: Draft Type: Project Vote: Pending Created: 23-Jan-2017 Post-History: Tcl-Version: 8.7 ----- # Abstract This TIP proposes to improve Tcl's handling of subprocesses created by the **exec** and **open** commands by adding a new **::tcl::process** ensemble. # Rationale This TIP is inspired by a <https://github.com/flightaware/Tcl-bounties\#stop-tcl-from-eating-child-process-exit-status-gratuitously%\|%request> from FlightAware%\|% to fix the way Tcl currently handles child process exit status. Subprocess creation can be either synchronous or asynchronous. In either case, a children with a non-zero return value indicates an error condition that is bubbled up to the Tcl error handling mechanism. ## Synchronous subprocesses Synchronous subprocesses are created using the **exec** command with no **&** terminal argument. Errors are raised synchronously as well. ## Asynchronous subprocesses Asynchronous subprocesses can be created using two distinct methods: * **exec** command with a **&** terminal argument. In this case the command returns immediately with a list of the PIDs for all the subprocesses in the pipeline. * **open "\| command"**. In this case the command returns immediately with the channel id of the pipe \(hereafter **$ch**\). The subprocess IDs are given by the **[pid $ch]** command. The subprocess status code and error conditions are processed upon channel closure with the **[close $ch]**. ## Error handling and status code Errors are caught with the **catch** and **try** commands, with status codes given in the **-errorcode** options dictionary entry and the **errorCode** global variable in the form **\{CHILDKILLED pid sigName msg\}** / **\{CHILDSTATUS pid code\}** / **\{CHILDSUSP pid sigName msg\}**. ## C-level access The Tcl library provides the following procedures for managing subprocesses \(excerpts from the Tcl documentation\): * **Tcl\_DetachPids** may be called to ask Tcl to take responsibility for one or more processes whose process ids are contained in the pidPtr array passed as argument. The caller presumably has started these processes running in background and does not want to have to deal with them again. * **Tcl\_ReapDetachedProcs** invokes the **waitpid** kernel call on each of the background processes so that its state can be cleaned up if it has exited. If the process has not exited yet, **Tcl\_ReapDetachedProcs** does not wait for it to exit; it will check again the next time it is invoked. Tcl automatically calls **Tcl\_ReapDetachedProcs** each time the exec command is executed, so in most cases it is not necessary for any code outside of Tcl to invoke Tcl\_ReapDetachedProcs. However, if you call **Tcl\_DetachPids** in situations where the exec command may never get executed, you may wish to call **Tcl\_ReapDetachedProcs** from time to time so that background processes can be cleaned up. * **Tcl\_WaitPid** is a thin wrapper around the facilities provided by the operating system to wait on the end of a spawned process and to check a whether spawned process is still running. It is used by **Tcl\_ReapDetachedProcs** and the channel system to portably access the operating system. Moreover, **Tcl\_WaitPid** is blocking unless called with the **WNOHANG** option. ## Limitations The current implementation is lacking several key features: * There is no way to get subprocess status other than through the error handling mechanism. * Consequently, there is no way to collect the status code of a asychronous subprocess created with the **exec &** method because such commands don't raise errors once the subprocesses are launched. * There is no non-blocking way to query asynchronous subprocess status codes; **catch**/**try** upon **open \|** pipe closure is blocking. * Moreover, **exec** and **open** call **Tcl\_ReapDetachedProcs**, thereby cleaning up all pending information on terminated subprocesses. This prevents any advanced subprocess monitoring at the script level. * While reasonable in the general case, a non-zero return value does not always indicates an error condition for all kinds of programs, so it is desirable to provide a subprocess-specific mechanism that does not rely on Tcl's standard error handling facility. # Specifications A new **::tcl::process** will be created: **::tcl::process** _subcommand ?arg ..._: Subprocess management. The following _subcommand_ values are supported by **::tcl::process**: * **::tcl::process list**: Returns the list of subprocess PIDs. * **::tcl::process status** _?switches? ?pids?_: Returns a dictionary mapping subprocess PIDs to their respective statuses. If _pids_ is specified as a list of PIDs then the command only returns the status of the matching subprocesses if they exist, and raises an error otherwise. The status value uses the same format as the **errorCode** global variable for terminated processes; for active processes an empty value is returned. Under the hood this command calls **Tcl\_WaitPid** with the **WNOHANG** flag set for non-blocking behavior. * **::tcl::process purge** _?pids?_: Cleans up all data associated with terminated subprocesses. If _pids_ is specified as a list of PIDs then the command only cleanup data for the matching subprocesses if they exist, and raises an error otherwise. If the process is still active then it does nothing. * **::tcl::process autopurge** _?flag?_: Automatic purge facility. If _flag_ is specified as a boolean value then it activates or deactivate autopurge. In all cases it returns the current status as a boolean value. When autopurge is active, **Tcl\_ReapDetachedProcs** is called each time the **exec** command is executed or a pipe channel created by **open** is closed. When autopurge is inactive, **::tcl::process purge** must be called explicitly. By default autopurge is active and replicates the current Tcl behavior. Additionally, **::tcl::process status** accepts the following switches: * **-wait**: By default the command returns immediately \(the underlying **Tcl\_WaitPid** is called with the **WNOHANG** flag set\) unless this switch is set. If _pids_ is specified as a list of PIDs then the command waits until the matching subprocess statuses are available. If _pids_ is not specified then it waits for all known subprocesses. * **--**: Marks the end of switches. The argument following this one will be treated as the first arg even if it starts with a -. # Examples % ::tcl::process autopurge true % ::tcl::process autopurge false false % set pid1 [exec command1 a b c | command2 d e f &] 123 456 % set chan [open "|command1 a b c | command2 d e f"] file123 % set pid2 [pid $chan] 789 1011 % ::tcl::process list 123 456 789 1011 % ::tcl::process status 123 {CHILDSTATUS 123 0} 456 {CHILDKILLED 456 SIGPIPE "write on pipe with no readers"} 789 {CHILDSUSP 789 SIGTTIN "background tty read"} 1011 {} % ::tcl::process status 123 123 {CHILDSTATUS 123 0} % ::tcl::process status 1011 1011 {} % ::tcl::process status -wait 123 {CHILDSTATUS 123 0} 456 {CHILDKILLED 456 SIGPIPE "write on pipe with no readers"} 789 {CHILDSUSP 789 SIGTTIN "background tty read"} 1011 {CHILDSTATUS 1011 -1} % ::tcl::process status 1011 1011 {CHILDSTATUS 1011 -1} % ::tcl::process purge % exec command1 1 2 3 & 1213 % ::tcl::process list 1213 # Rejected Alternatives The first version proposed to implement the feature as a new **ps** option to the existing **info** command. However, almost all operations in **[info]** are things that just examine state, not change it, and that's a principle-of-least-astonishment that should be upheld for the sake of less experienced users. # Reference implementation TBD # Copyright This document has been placed in the public domain. |
Name change from tip/463.tip to tip/463.md.
|
| < | | | | | | < | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 463: Command-Driven Substitutions for regsub State: Final Type: Project Tcl-Version: 8.7 Vote: Done Post-History: Author: Donal Fellows <[email protected]> Created: 11-Feb-2017 Keywords: Tcl, regular expression ----- # Abstract The **regsub** command can only do substitutions of a limited complexity. This TIP adds an option to generate substitution text using another Tcl command, allowing a more complex range of substitutions to be performed easily and safely. # Rationale and Outline Proposal Many scripts wish to perform subsitutions on a string where the text to be substituted can be described by a regular expression, but where the text to be substituted in cannot easily be generated by the **regsub** command. There are workarounds for this, as seen in this example \(from the Wiki\): set text [subst [regsub -all {[a-zA-Z]} [\ regsub -all "\[\[$\\\\\]" $text {\\&}] {[ set c [scan & %c] format %c [expr {$c\&96|(($c\&31)+12)%26+1}] ]}]] But it is not at all trivial to write such things! Instead, we should be able to do this: set text [regsub -all -command {[a-zA-Z]} $text {apply {c { scan $c %c c format %c [expr {$c&96|(($c&31)+12)%26+1}] }}}] It's going to be both safer \(as there's no required non-obvious metadata defanging preprocessing step\) and faster \(as we can do this as a command call rather than a **subst** that needs separate bytecode compilation\). The parallels with Perl's "e" flag to its regular expression substitution operator should be obvious. # Proposed Change My proposal is that we add a flag to the **regsub** command, **-command**, that changes the interpretation and processing of the substitution argument. When the flag is passed, instead of that argument being a string that is processed for **&** and backslash-number sequences, it is instead interpreted as a command prefix; the various captured substrings \(minimally the entire string passed in, but also any captured substrings specified in the RE\) will become extra arguments added, and the result will be evaluated and the result of that evaluation will be used as the string to substitute in. If the **-all** option is not given, the substitution command will be called at most once, whereas if **-all** is given, the substitution command will be called for as many times as the regular expression matches. The indices in the original script that matched will not be available. Non-OK results will be passed through to the surrounding script. Substitutions too complex to be described by a simple command can be done by using a procedure or **apply**/lambda-term \(as in the example above\). The arguments received by the command invoked by **regsub -command** will be exactly the substrings that were matched, with no other substitutions performed on them. ## Examples The command: regsub -all -command {\w} "ab-cd-ef-gh" { puts } will give **---** as its result and print the letters **a** to **h**, one per line in that order. The command: regsub -command {\W(\W)} "ab cd,{ef gh,} ij" {apply {{x y} { scan $y %c c format %%%02x $c }}} will produce this result: ab cd%7bef gh,} ij # Implementation <http://core.tcl.tk/tcl/timeline?r=tip-463> # Copyright This document has been placed in the public domain. |
Name change from tip/464.tip to tip/464.md.
|
| < | < | | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 464: Support for Multimedia Keys on Windows Author: Ralf Fassel <[email protected]> Author: Andreas Leitgeb <[email protected]> State: Final Type: Project Vote: Done Created: 28-Jan-2017 Post-History: Keywords: Tk,keyboard,keycode Tcl-Version: 8.5 ----- # Abstract This TIP proposes adding support for the multimedia keys present on many modern keyboards. # Rationale Tk is lacking support for the multimedia keys as described on <https://msdn.microsoft.com/en-us/library/windows/desktop/dd375731%28v=vs.85%29.aspx> VK_VOLUME_DOWN 0xAE Volume Down key VK_VOLUME_UP 0xAF Volume Up key VK_MEDIA_NEXT_TRACK 0xB0 Next Track key VK_MEDIA_PREV_TRACK 0xB1 Previous Track key VK_MEDIA_STOP 0xB2 Stop Media key VK_MEDIA_PLAY_PAUSE 0xB3 Play/Pause Media key Linux supports these as, e.g., XF86AudioPlay, XF86AudioPrev, XF86AudioNext. Tk should support them as well so that application programmers can make use of the keys as appropriate. Because this is driven by changing external circumstances, it is propsed that this TIP be backported to all future-releaseable versions of Tk \(i.e., 8.5 onwards\). # Proposal The table of supported keys should be extended to include the following named keys: * **XF86AudioLowerVolume** - the volume-down key * **XF86AudioMute** - the volume-mute key * **XF86AudioNext** - the next-track key * **XF86AudioPlay** - the start-playback key * **XF86AudioPrev** - the previous-track key * **XF86AudioRaiseVolume** - the volume-up key * **XF86AudioStop** - the stop-playback key The above list does not imply any ordering in the implementation. # Implementation The support can be added by extending some keymapping lookup tables in Tk. A Ticket already exists with a proposed patch <http://core.tcl.tk/tk/tktview/499526180d6cd5ca7c02eed96c10e9d3630a807c> and fvogel has also created a branch <http://core.tcl.tk/tk/timeline?r=tip-464> . # Copyright This document has been placed in the public domain. |
Name change from tip/465.tip to tip/465.md.
|
| < | < | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 465: Change Rule 8 of the Dodekalogue to Cut Some Corner Cases Author: Andreas Leitgeb <[email protected]> State: Draft Type: Project Vote: Pending Created: 03-Mar-2017 Post-History: Tcl-Version: 8.7 ----- # Abstract This TIP proposes to make **$**-substitution more conforming to naive expectations and just rule out certain odd-ball uses that can safely be assumed to not appear in serious use, but only in crafted examples "serving" for confusion, or as accidentally legal interpretation of mistyped Tcl code. # Rationale Back in the days where **$**-substitution was added to Tcl, it was designed to be as syntactically simple as possible. Back then, Tcl was still an interpreted language, so optimising parse time was top priority. For this, it was designed that a sequence starting with **$\{** would end at the **next close brace** no matter how many open braces or backslashes are passed by, and **$arr\(** would end at the **next close paren** no matter how many open parens are found before. This enables odd-ball corner cases that work in an interactive shell at top level, as tried by newbies: set "{{{" 42; puts ${{{{} but fail within a braced block, unless a comment like: # }}} }}} follows within the same block. These are just strange parts of Tcl, that nobody can seriously claim to use for good. Another surprising part is with arrays, where parens are treated asymmetrically, in that any number of bare open parens, but also quote chars or braces may be part of the index in a **$arr\(...\)** substitution, but first bare close paren terminates the token. Quote characters or braces have no significance, apart from that bare close braces might pre-maturely finish the enclosing braced block, which may only be evident to seasoned Tclers - and not even always to them. The final motivation for writing up this TIP came while discussing one part of [[282]](282.md): assignment to array elements. An informal poll showed a clear preference towards bare **array\(...\)** naming on left hand side of proposed assignment, without sympathy for any need of explicit disambiguation by quoting or tagging. Generally disallowing bare open parens, quotes and braces within array indices would mean that array indices on left hand side of an assignment could follow same rules as on right hand side, and parsing an array by these new rules would make sure, that where parsing as a function call and parsing as an array are both successful, then both parses would end up consuming the same portion of the expression body - a prerequisite for making a sound decision about following assignment operator. Without having array parses and function parses agreeing on close paren, then it is possible that parsing as an array will see a trailing assignment operator that would otherwise have been nested in a subexpression, or even part of a quoted literal value. Because of the low expected impact on real code, a target of 8.7 is considered feasible. # Implementation A full implementation of this TIP is now checked in on branch _tip-465_. # Alternatives The following points show alternatives that would make sense, but would make the currently rather simple implementation of this TIP ways more complicated: * Allow bare parens in array indices if properly paired. Quotes and braces are still disallowed \(even if paired\), to avoid cases of bad nesting: **\{\(\}\)**. This might save users two backslashes in some rare cases where a close paren in the index is already backslash-escaped. * Specifically add backslash-quoting to the "body" of **$\{...\}**. After all, the "body" is a variable name, and not a nested structure like most braced words in Tcl. This would make some odd variable names once again possible, but now in a consistent syntax that doesn't affect enclosing blocks. * **$\{...\}** syntax could also be further restricted by disallowing open braces and final backslashes, just to enforce "well-behaving" tokens. * A much stricter alternative would disallow unbalanced braces even within "-quoted and unquoted literals. This would disallow common but dangerous idioms like _append var "\{"_, which may be followed by an _append var "\}"_ in the same block and work, until one of these two commands gets moved into a nested block. The correct and safe way is, of course, backslash-escaping bare braces within string literals. Good Code\(tm\) wouldn't be affected by this alternative change. # Copyright This document has been placed in the public domain. |
Name change from tip/466.tip to tip/466.md.
|
| < | < | | | | | | | | | > | | | | 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 | # TIP 466: Revised Implementation of the Text Widget Author: François Vogel <[email protected]> Author: Gregor Cramer <[email protected]> State: Draft Type: Project Vote: Pending Created: 10-Mar-2017 Post-History: Keywords: Tk,text widget Tcl-Version: 8.7 ----- # Abstract This TIP proposes the replacement of the current implementation of the text widget \(the "legacy" text widget\) by a revised implementation offering a large number of advantages. # Rationale The Tk text widget has become increasingly complex as long as incremental improvements and features have been added from time to time. In that process, some known long-standing issues have become very difficult to tackle, for instance the long line problem regarding lack of performance. Gregor Cramer, in the process of using the text widget in one of his |
︙ | ︙ | |||
35 36 37 38 39 40 41 | * A large number of new features * Numerous bug fixes * Very few incompatibilities with the legacy text widget | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 | * A large number of new features * Numerous bug fixes * Very few incompatibilities with the legacy text widget # Proposal The proposal is to replace the legacy code with the new implementation. The author of the revised implementation has written a well documented website <http://scidb.sourceforge.net/tk/revised-text-widget.html> describing in details the issues with the legacy code, how he fixed these issues, and what features he has changed or improved. It was not deemed feasible nor necessary to copy/paste/reformat all the information of the above website into the present TIP. Only the new features and incompatibilities are highlighted here, as opposed to detailed rationales about each change. A version of the **text** man page, consistent with the changes and improvements proposed by the present TIP, can be seen at <http://scidb.sourceforge.net/tk/text.html> This version of the man page is colorized, with blue meaning "changed", and green meaning "new", so that it is easier to spot what's different from the legacy text widget. ## Performance Improvements Detailed performance comparison between legacy code and revised code can be found at <http://scidb.sourceforge.net/tk/comparison.html> but these are the key points: * Long line problem, especially with many tags, is eliminated: in general only O\(N log N\) in revised version, was a higher order polynomial time in legacy code. * Display is faster: smoother scrolling, faster response time. <http://scidb.sourceforge.net/tk/display.html> * Undo/redo is much faster: a completely new implementation has been worked out, directly working on the text segments. <http://scidb.sourceforge.net/tk/undo.html> ## New Features Detailed explanations and rationales for each of the items below can be found at <http://scidb.sourceforge.net/tk/revised-text-widget.html> * Undo/redo is handling tags \(this was requesteed in Issue \#1561991 and Issue \#1027741, embedded images, embedded windows, and also marks if option _-steadymarks_ is enabled * Additional widget state **readonly** * Hyphenation and full-justification support > \* Support of hyphenation \(Issue \#1096580 is fixed\), with new helper functions **tk\_textinsert** and **tk\_textReplace**, and with new switches to _pathName_ **count**, _pathName_ **get**, and _pathName_ **search** > \* Additional justification mode **full** > \* Additional wrap mode **codepoint**, and new widget option **-useunibreak**. New subcommand _pathName_ **brks** > \* Additional option **-lang** used to guide hyphenation engines. * Additional subcommands: > \* _pathName_ **checksum** > \* _pathName_ **clear** > \* _pathName_ **edit altered** > \* _pathName_ **edit info** > \* _pathName_ **edit inspect** > \* _pathName_ **edit irreversible** > \* _pathName_ **edit recover** > \* _pathName_ **inspect** > \* _pathName_ **isclean** > \* _pathName_ **isdead** > \* _pathName_ **isempty** > \* _pathName_ **lineno** > \* _pathName_ **load** > \* _pathName_ **mark compare** > \* _pathName_ **mark exists** > \* _pathName_ **mark generate** > \* _pathName_ **tag clear** > \* _pathName_ **tag findnext** > \* _pathName_ **tag findprev** > \* _pathName_ **tag getrange** > \* _pathName_ **tag priority** > \* _pathName_ **watch** * Additional tag attributes: > \* **-eolcolor** > \* **-hyphencolor** > \* **-hyphenrules** > \* **-inactivebackground** > \* **-inactiveforeground** > \* **-inactiveselectbackground** > \* **-inactiveselectforeground** > \* **-indentbackground** > \* **-undo** * Additional widget options: > \* **-endindex** > \* **-eolchar** > \* **-eolcolor** > \* **-eotchar** > \* **-eotcolor** > \* **-hyphencolor** > \* **-hyphenrules** > \* **-hyphens** > \* **-inactiveselectforeground** > \* **-insertforeground** > \* **-maxredo** > \* **-maxundosize** > \* **-responsiveness** > \* **-showendofline** > \* **-showendoftext** > \* **-showinsertforeground** > \* **-spacemode** > \* **-startindex** > \* **-steadymarks** > \* **-synctime** > \* **-tagging** * Extensions to the syntax for indices: > \* new specifier **begin** > \* new syntax _tag_.**current.first**, _tag_.**current.last** > \* new syntax **@first,last** * Additional features of existing subcommands: > \* Additional option **-marks** for _pathName_ **delete** command > \* Additional optional parameter _direction_ for _pathName_ **mark set** sub-command > \* New virtual event **<<Altered>>** to support new sub-command _pathName_ **edit altered** > \* Extensions to commands _pathName_ **edit reset** and _pathName_ **edit separator** * Extended command _pathName_ **tag names** * Additional switch for _pathName_ **dump** * Additional option **-extents** for _pathName_ **bbox** and _pathName_ **dlineinfo** * Additional option **-discardspecial** for _pathName_ **mark names**, _pathName_ **mark next**, and _pathName_ **mark previous**. * Additional optional parameter _pattern_ for _pathName_ **mark names**, _pathName_ **mark next**, and _pathName_ **mark previous**. * New helper commands: > \* **tk\_mergeRange** > \* **tk\_textInsert** > \* **tk\_textReplace** > \* **tk\_textRebindMouseWheel** * Additional option **-owner** for embedded window * Additional option **-tags** for embedded images and embedded windows ## Bug Fixes * Bug fixed in TkTextGetIndex * Bug fixed in TkTextGetIndexFromObj * Bug fixed in DeleteIndexRange \(note that this bugfix implies that deletion at the end of the text handles the last newline now differently - slight incompatibility with the legacy text widget\) * Bug fixed in TkTextDeleteTag/TagBindEvent * Problems fixed with **-startline**/**-endline** * Problems fixed with tag event handling * Several bug fixes with **undo_ * **Edit modified** confusing results fixed with new command **edit altered** * Severe problems with command **sync** fixed * Invalid changes in disabled widget are marked as deprecated * Inaccurate wrapping algorithm fixed * Bugs in display logic fixed * Insert cursor is now fully visible in all conditions * Trimming spaces: Issue \#1082213 is invalid, the fix put in trunk \(8.7\) has been reverted \(but there is now the new option **-spacemode** that can be set to **trim**\) * Issues with display of selections fixed * **Update** is no longer wasting the processor time since superfluous update computations are not done anymore * Bugs in context drawing support \(OS X\) fixed * Bugs fixed in tkUnixRFont.c * Several bug fixes related to handling/positioning of the insertion cursor Details on each of these bugs can be found in the "Bugs/Issues in Original Implementation" section at <http://scidb.sourceforge.net/tk/revised-text-widget.html> ## Incompatibilities with Legacy Version Based on the author's website, the following incompatibilities are currently known: * [[449]](449.md) \(undo/redo to Return Range of Characters\) was not adapted into the revised implementation, because Issue \#1217222 - the basis for [[449]](449.md) - is now featured by: > 1. The new undo implementation, because also the tag associations will be restored, and > 2. The powerful **watch** command, which also provides the affected ranges \(with constant runtime behavior\). > Moreover, the **tk\_mergeRange** function convenience function has been implemented in the revised version. * The special selection tag **sel** can no longer be elided \(would be useless anyway\). * Tag options \(introduced in 8.6.6\) -overstrikefg and -underlinefg were renamed to **-overstrikecolor** and **-underlinecolor** * The new index syntax **@first,last** is incompatible with the legacy version but it is not expected that any existing application will break, certainly nobody is using such a form for the name of a mark or image * The default value of 50 ms for the new **-responsiveness** option is incompatible to prior releases, but it shouldn't matter here, because nobody wants flickering, and nobody is using special tricks with a short mouse hovering while the widget is scrolling. Setting the responsiveness to zero restores the old behavior of the text widget. * <<UndoStack>> is generated with any change on the undo stack, not only when the undo stack or the redo stack becomes empty or non-empty * **-startline**/**-endline** behavior was subtly changed in some corner cases * In revised implementation "\+N chars" and "-N chars" refer to characters, and no longer to indices \(which was the case in legacy code for backwards compatibility reasons\). ## Deprecated Commands and Options * Tag options \(introduced in 8.6.6\) **-overstrikefg** and **-underlinefg** were renamed to -overstrikecolor and -underlinecolor * edit **undodepth**\|**redodepth**\|**canundo**\|**canredo** are replaced by more general **edit info** * Widget options **-startline**/**-endline**' are replaced by -startindex/-endindex ## Drawbacks * The increase in memory usage is not very high \(but a bit high\), and despite this, in many cases, especially if many tags are used, and/or undo is enabled, the revised version is even decreasing the memory usage. Detailed memory comparison between legacy code and revised code can be found at <http://scidb.sourceforge.net/tk/comparison.html> ## Known Issues in the Revised Implementation Based on the author's website, currently only these issues are known: * The code for the implementation has increased by more than 100%, and about 70% of the old code has been changed. The revised implementation needs more testing, the text widget is very complex, and bugs are expected. And a few additions are not yet well tested. * Function **tk\_textCopy** is copying hidden \(elided\) text. This seems to be unexpected, but it's the behavior of the original implementation. Probably this is a bug and should be corrected. * Adding/deleting tags covering a large range of text is still quite time consuming. * The display line with the insert cursor is redrawn each time the cursor blinks, which causes a steady stream of graphics traffic. It would be desirable if the cursor update will be performed with a specialized and efficient redraw function. * If option **-spacemode** is set to trim, then **get -displaychars** should probably return trimmed spaces. Currently this command is not trimming spaces, so the result may not coincide with the visible text. * The **search -regexp** sub-command is still not yet fully implemented, see Tk documentation. * The revised widget still ignores modifying commands if state is not normal; this behavior is unreasonable, but conforms to the original version. * Currently the special index specifier **begin** has the lowest precedence, although it should have the same precedence as the special index special **end** \(see section INDICES\). In a future release this should be corrected. The current behavior is a workaround, avoiding that existing applications will break with the introduction of **begin**. * The implementation still contains some TODO's of minor issues. Also, the following should be noted: * With the revised version there are failing tests on all platforms, they need to be fixed \(by fixing the expected result in the test, or by fixing the text widget code\). * More tests should be written to exercise the new or changed features. * The OS X case should be more tested on a real Mac, because it's the only platform using context drawing. ## Miscellaneous * No function signature pertaining to a public interface was changed. Also public data structures haven't been touched. * All recent new features brought in trunk in the legacy version have their counterpart in the revised version, have been improved in performance and have no known drawbacks. Minor incompatibilities are however identified here and there. # Target Release Given the amount of changes, also because of our usual precautions regarding backwards compatibility, and despite the very high quality of the code and the fact it passes \(almost all\) the previously existing test suite, it is deemed reasonable to target Tcl/Tk 8.7 \(or 9.0\), but neither the 8.6 nor the 8.5 streams of releases, which will continue to implement the legacy text widget code. Support of versions back to 8.5 is currently included in the revised code, but will be removed \(because it's useless for use in trunk only\) at the time the new code will get merged into trunk. # Implementation Implementation of the revised text widget code has been placed in branch <http://core.tcl.tk/tk/timeline?r=revised_text> of the fossil repository. This implementation compiles on Linux, Windows, and OS X. It respects the standards of Tk \(C99 standard, and also the Tcl source code formatting described in [[247]](247.md)\). The man page for the text widget has been contributed by jima and is included in the revised\_text branch. The expected results of many tests were adjusted to take into account that the revised implementation is better optimizing, so some trace results of display line computation are different. Other adjustments were required because of bug fixes. # Open Questions * tkTextUndo.c implements a specialized undo/redo, not using the legacy tkUndo.c. Reasons for this are stated at the top of tkTextUndo.c. It is interesting to note that, in the revised\_text branch, tkUndo.c is not even compiled anymore, except on Linux \(for no apparent reason\). This is dead code waiting for use case by a widget. At least, compilation on Linux should be removed, but couldn't we even rename tkTextUndo.c to tkUndo.c and forget about the old implementation? tkTextUndo.c is also a shareable implementation \(in the spirit of [[104]](104.md)\). * Actual removal of deprecated features or keep them \(some are marked as deprecated, but actually still supported\)? # Copyright This document has been placed in the public domain. The author of the revised text widget code has explicitly placed his code of the text widget under the same license as Tcl. |
Name change from tip/467.tip to tip/467.md.
|
| < | < | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 467: Move TIP Collection to Fossil Author: Mark Janssen <[email protected]> State: Draft Type: Process Vote: Pending Created: 14-Mar-2017 Post-History: Keywords: migration ----- # Abstract The Tcl TIP collection shall be moved to Fossil and the process of managing TIPs shall use Fossil as much as possible. The TIP format will be changed from a TIP-specific form to Markdown. # Rationale Triggered by some people having issues with changing content on current TIP website and discussion on the \#tcl chat, I have experimented with fossil as a medium to host the Tcl TIP collection. The current TIP storage and handling requires a lot of scripts that need to be maintained by the TCT and it is less open than it could be. There are also advantages to switching to Fossil in place of CVS. * Fossil has embedded Markdown rendering. * Fossil is already used to manage the Tcl and Tk sources. * TIP discussion and CFVs can be done and tracked using fossil tickets. * Fossil events could also track CFV's and Vote results * CVS is extremely vulnerable to problems with system administration on a single host. With a fossil-based system, it is much simpler to have multiple repositories. Besides Fossil supporting Markdown out of the box, markdown is also better option for the future than the current format. The value of making up your own plain text format in this age is debatable \(especially for the TIP requirements\). Markdown has widely available options to convert to other formats without any need for the community to maintain the converters, and supports key extra features such as embedded images \(which are important for some Tk TIPs, and never worked particularly well with the old TIP format\). # Specification Proposed URL for the new repository will be <http://core.tcl.tk/tips> ## Backwards compatibility * _tip.tcl.tk/<NUM>.html_ should still show a rendered result. This could be redirected to _core.tcl.tk/tips/doc/trunk/tip/<NUM>.md_ * _tip.tcl.tk_ offers several converted formats \(XML, \*roff, ...\). The fossil option will be to use the _core.tcl.tk/tips/file/tip/<NUM>.md?download_ URL to get the raw Markdown downloads. For getting the other options one could convert the markdown source file using something like pandoc. * E-mail address are not hidden in the source and in the rendered result. If e-mail addresses need to be hidden there are two options 1. Remove mails from source. 2. Hide e-mails in fossil. 3. Hide e-mails in the webhost. Option 2. doesn't help much as the mails are still online in the raw markdown files. Option 1. loses information. Suggested is to leave the addresses untouched. ## Process TBD ## TIP Format The Markdown tip format has one extension to standard Markdown: Any TIP.md file will have a mandatory preamble starting with the title \(for fossil rendering\) and ending with a \`------\` on a single line. Between these parts there is tab indented meta information about the tip. \(Tab indented so it renders nicer in fossil, 4 spaces would also work\) Example from [[0]](0.md): # TIP 0: Tcl Core Team Basic Rules State: Final Type: Process Vote: Done Post-History: ------ # Implementation * There is a proof of concept conversion \(with CVS history\) at <https://fossil.mpcjanssen.nl/tips> * The scripts for the automatic conversion are at <https://fossil.mpcjanssen.nl/tip-migration> # Copyright This document has been placed in the public domain. |
Name change from tip/468.tip to tip/468.md.
|
| < | < | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 468: Support Passing TCP listen Backlog Size Option to TCP Socket Creation Author: Shannon Noe <[email protected]> State: Draft Type: Project Vote: Pending Created: 03-Apr-2017 Post-History: Keywords: Tcl, socket, SOMAXCONN Tcl-Version: 8.7 ----- # Abstract This TIP adds the ability to control the TCP backlog depth used by the _listen_ system call within the **socket** Command. The API function, **Tcl\_OpenTcpServerEx**, will be extended to allow the passing of the backlog value. Currently, the SOMAXCONN macro is used as the default. Backlog values are hard coded to a minimum of 100. The backlog values of 1 and 0 are useful on the Linux platform. # Rationale Modern Linux TCP supports the kernel managing the listen queue for TCP sockets. Multiple processes open the same socket address and ports with SOREUSEADDR and SOREUSEPORT. Each process then uses a backlog value of 1 to process a single connection at a time. This is explained in detail on this website <http://veithen.github.io/2014/01/01/how-tcp-backlog-works-in-linux.html> Tighter control over this would allow Tcl scripts to have tighter control over whether to support a large backlog of sockets waiting to be opened. \(Exceeding the limit would cause the OS to automatically reject the socket connection, which might be preferable in some high-availability situations to being blocked for an unknown amount of time.\) # Specification A **Tcl\_OpenTcpServerEx** function will be changed to add a _backlog_ parameter with this signature: > Tcl\_Channel **Tcl\_OpenTcpServerEx**\(Tcl\_Interp \*_interp_, const char \* _service_, const char \*_myHost_, unsigned int _flags_, int _backlog_, Tcl\_TcpAcceptProc \*_acceptProc_, ClientData _acceptProcData_\) As for the Tcl side, the **socket** command gains a new optional switch that are only valid for server sockets: ?**-backlog** _int_?. Omitting the parameter will cause the default value to be used. Tcl code includes local macro’s for SOMAXCONN which override all platforms values for SOMAXCONN. This makes backwards compatibility easier. We only need to preserve the macro value in the default code path. # Reference Implementation Please refer to the _tip-???_ branch of the core Tcl repository. # Backwards Compatibility The **Tcl\_OpenTcpServerEx** will retain the old behavior by default as SOMAXCONN. The SOMAXCONN is defined by macros in the Tcl source. All Tcl code paths with a listen\(\) system call pass a backlog value. No new code paths are introduced, only new values for the listen backlog parameter. The **socket** command will be backwards compatible. The default **-backlog** parameter is set to _SOMAXCONN_. Omission of the new parameter provides the current behavior. # Copyright This document has been placed in the public domain. |
Name change from tip/469.tip to tip/469.md.
|
| < | < | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 469: A Callback for Channel-Exception Conditions Author: Andreas Leitgeb <[email protected]> State: Draft Type: Project Vote: Pending Created: 16-Apr-2017 Post-History: Keywords: Tcl,event handling Tcl-Version: 8.7 ----- # Abstract This TIP proposes to extend the **fileevent** Tcl command to also accept the keyword **exception** for its second argument. This will allow to register a callback for the specific event that the OS reports an exception on the channel, while ignoring read- or writability. # Rationale Tcl already allows registering for exceptions in its C-API function Tcl\_CreateChannelHandler\(\). This TIP merely enables the command **fileevent** to pass TCL\_EXCEPTION for the mask in the call to Tcl\_CreateChannelHandler\(\). On Linux, there exist special "files" that are always readable or writable without blocking, but certain \(hardware-related\) events are reported as exceptions on the channel. The example at hand is the "sysfs"-API for GPIO \(general purpose input output\) where level-changes on GPIO pins are reported as exceptions on the channel. For details see <https://www.kernel.org/doc/Documentation/gpio/sysfs.txt> and the paragraphs about "value". Listening for readable plus exceptions \(as Tcl automatically does when asking for readable event\) doesn't help here, because then the event would continuously fire, as reading the current level on a pin never blocks. The only way to react to level-changes \(short of busy-looping\) is to have the internal select/poll call specify exclusively the exception notification for that channel. # Specification This document proposes to add the keyword **exception** to the **fileevent** command, where so far only **readable** and **writable** are allowed. If **exception** is given as event specifier, then a handler script is registered, cleared or queried just like with **readable** or **writable**. Since **readable** or **writable** already check for exception as well, registering an exception event for a channel that already has readable and/or writable handlers registered makes little sense, but allowing it does not raise any issues that having both readable and writable handlers wouldn't already have, so being fussy about it would confuse more than it could help to avoid confusion. # Alternatives The _piio_ extension provides event registration on its own, but its support for certain IO-chipsets lags behind the sysfs-API. With **exception** becoming its own event type, then **readable** and **writable** would no longer need to also fire on exceptions, but compatibility forbids this particular follow-up change. # Compatibility No incompatibilities are introduced. # Reference Implementation A really bare-bones reference implementation is available as a patch <http://paste.tclers.tk/4231> . Also, a branch named tip-469 in fossil has been created: <https://core.tcl.tk/tcl/timeline?r=tip-469> . A thus-patched tclsh can successfully wait for input-level changes on TIP-author's "nano-pi" raspberryPI-like platform with a chipset not yet supported by piio. Documentation and test updates yet to be done. # Copyright This document has been placed in the public domain. |
Name change from tip/47.tip to tip/47.md.
|
| < | < | | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | < > | < > | | | | | | | | < > | | | | | < > | | < > | | < > | | | | | | | | | > | 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 | # TIP 47: Modifying Tk to Allow Writing X Window managers Author: Neil McKay <[email protected]> Author: Andreas Kupries <[email protected]> Author: Donal K. Fellows <[email protected]> State: Final Type: Project Vote: Done Created: 19-Jul-2001 Post-History: Tcl-Version: 8.4 ----- # Abstract With a few modifications to the Tk core, extensions could be written that would allow X window managers to be implemented as Tcl/Tk scripts. # Requirements Writing X window managers in Tk requires some facilities that the current Tk core doesn't provide. A window manager must be able to: * draw to, and handle events on, the display's root window \(including _<Create>_, _<MapRequest>_, _<ResizeRequest>_, _<CirculateRequest>_, and _<ConfigureRequest>_ events, which are currently ignored\) * embed arbitrary windows inside Tk windows * receive _<PropertyNotify>_ events from embedded windows * perform a variety of other X-specific operations Window embedding can be handled by an extension, if it is not incorporated into the Tk frame widget at some later time. Likewise, the X-specific operations can be handled by an extension. However, Tk as it currently stands cannot access the display's root window, nor can _<PropertyNotify>_ events be received from embedded windows; doing these things requires core modifications. # Root Window Access The root window is special in many ways: * It does not need to be created * It cannot be destroyed, moved, or resized * Only one process can receive _<ButtonPress>_ and _<ButtonRelease>_ events from it, and only one process can have the _SubstructureRedirect_ and _ResizeRedirect_ masks set * It has no physical parent window Because of these properties, access to the root window via a Tk widget presents some difficulties. First, the widget's window cannot be created in the standard way; however, this problem may be solved by providing a non-standard creation routine via the _Tk\_SetClassProcs_ procedure described in [[5]](5.md). Likewise, the event handling required by the root window can be enabled in an extension, although some care is required when enabling _<ButtonPress>_ and certain other events. What really causes problems is the lack of a physical parent. There are many places in Tk where it is assumed that only toplevel widgets have no physical parent within the application; this is reflected in the Tk source by the use of the _TK\_TOP\_LEVEL_ flag. This flag is used to mean different things in different places. In particular, the _TK\_TOP\_LEVEL_ flag may mean: * This window is a toplevel widget * This widget has a wrapper window * This widget's window is controlled by the window manager * This window is at the top of a physical window hierarchy within the current application In the current version of Tk, toplevel widgets have all of these properties, and no other widgets have any of these properties; hence a single flag suffices. If we create a widget whose window is the display's root, then this is no longer the case; a root window has the last property, but not the first three. For this reason, it is necessary to replace the _TK\_TOP\_LEVEL_ flag with at least two distinct flags. A better idea is to replace the _TK\_TOP\_LEVEL_ flag with four flags, one for each of the properties listed above. \(Even in a standard Tk distribution, this replacement is desirable for documentation reasons, since it will indicate what property of a toplevel widget is important in the current circumstances.\) We must also replace the _Tk\_IsTopLevel_ macro with several macros, or just eliminate it entirely. One possible set of flag names is: TK\_TOP\_LEVEL: this is a toplevel widget TK\_HAS\_WRAPPER: this window has a wrapper window TK\_WIN\_MANAGED: this window is controlled by the window manager TK\_TOP\_HIERARCHY: this window is at the top of a physical window hierarchy # New Event Bindings and Substitutions A window manager must be able to intercept certain events on the root window that the standard Tk distribution doesn't recognize, and it must be able to obtain information about those events. In particular, it needs to respond to _<CirculateRequest>_, _<ConfigureRequest>_, _<CreateNotify>_, _<MapRequest>_, and _<ResizeRequest>_ events. These events are ignored by standard Tk, and need not be enabled by default; however, they need to be included in the list of events recognized by the Tk _[bind]_ command. Adding this facility is very simple. Obtaining information about these events is also necessary. This is usually done via %-substitutions in the _[bind]_ command; however, there are two pieces of information that are necessary for implementing a window manager that cannot be obtained via the current %-substitution mechanism: the numerical X window ID, required to handle _<CreateNotify>_ events, and the property name, for handling _<PropertyNotify>_ events. This information could be obtained by adding two new %-substitutions: %i: substitute the numerical window ID for the event %P: substitute the atom name for the property being changed # Propagating <PropertyNotify> Events In order to receive _<PropertyNotify>_ events from embedded windows, the Tk event loop must handle events not just for windows that are represented by _Tk\_Window_ structures, but also for their children. One way to accomplish this is to add another flag for the _Tk\_Window_ struct, and alter the event loop so that it will also look at a window's parent, if the event is a _<PropertyNotify>_ event. The relevant part of the Tk event loop currently looks like this: winPtr = (TkWindow *) Tk_IdToWindow(eventPtr->xany.display, handlerWindow); if (winPtr == NULL) { if (eventPtr->type == PropertyNotify) { TkSelPropProc(eventPtr); } return; } If the flag for propagating _<PropertyNotify>_ events is _TK\_PROP\_PROPCHANGE_, then the code above must be modified to look approximately like this: winPtr = (TkWindow *) Tk_IdToWindow(eventPtr->xany.display, handlerWindow); if (winPtr == NULL) { if (eventPtr->type != PropertyNotify) { return; } TkSelPropProc(eventPtr); parentXId = (parent of handlerWindow); winPtr = (TkWindow *) Tk_IdToWindow(eventPtr->xany.display, parentXId); if (winPtr == NULL) { return; } if (!(winPtr->flags & TK_PROP_PROPCHANGE)) { return; } handlerWindow = parentXId; return; } # Patches A patch \(against tk8.4a2\) that implements the changes described above is available <http://www.eecs.umich.edu/~mckay/computer/wmenablers.84a3.patch.gz> . # Notes _Andreas Kupries._ There was a _tkwm' patch once. <http://www.neosoft.com/tcl/ftparchive/sorted/x11/tkwm/> <http://www.ensta.fr/internet/unix/window_managers/tkwm.html> # Copyright This document is in the public domain. |
Name change from tip/470.tip to tip/470.md.
|
| < | | | | | | < | | | > | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 470: Reliable Access to OO Definition Context Object State: Final Type: Project Tcl-Version: 8.7 Vote: Done Post-History: Author: Donal Fellows <[email protected]> Created: 23-Apr-2017 Keywords: TclOO, metaprogramming ----- # Abstract This TIP makes it easier for people to write procedures to extend TclOO's definition sublanguage. # Rationale One of the fundamental features of Tcl is that you can extend it with more capabilities by writing your own procedures \(and other commands, if you prefer the C API\). However, it is somewhat awkward to do so when using TclOO, as the **oo::define** and **oo::objdefine** commands don't make it easy to find out what the context class or object is. For example, in the _oo::util_ package of Tcllib, the code for discovering what the context class is includes this <http://core.tcl-lang.org/tcllib/artifact/51d71f560ceb7d63?ln=77> : # Get the name of the current class or class delegate set cls [namespace which [lindex [info level -1] 1]] That is ugly, and won't even work reliably for getting the context object in **oo::objdefine** as that can be entered into by multiple paths \(i.e., there's a shortcut from **oo::define**\). # Proposed Change I propose to make the existing **self** command in **oo::define**, when invoked without arguments, return the context class \(provided it is evaluated in the correct stack frame, as usual with definition commands\). Similarly, I also propose to add a **self** command to the **oo::objdefine** system that takes no arguments and returns the context object. This will enable to code listed above in the _Rationale_ to become: # Get the name of the current class or class delegate set cls [uplevel 1 self] In the C API, I propose adding a function: > Tcl\_Object **Tcl\_GetDefineContextObject**\(Tcl\_Interp \*_interp_\) which will get the context object, or return NULL and put an error in the interpreter if there is no context object in the frame or the context object has been deleted. The functionality is that of **TclOOGetDefineCmdContext** in _tclOODefineCmds.c_ <http://core.tcl-lang.org/tcl/artifact/7d58f1a701168168?ln=682> , but the text of the error messages might be changed. # Copyright This document has been placed in the public domain. |
Name change from tip/471.tip to tip/471.md.
|
| < | < | | | | | | | > | | | | | | | | | | | | | | | | | | > | 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 | # TIP 471: Add [info linkedname] Introspection Command Author: Mathieu Lafon <[email protected]> State: Draft Type: Project Created: 05-May-2017 Tcl-Version: 8.7 Vote: Pending Post-History: ----- # Abstract This TIP proposes to improve link variable introspection by providing a new **info linkedname** command. # Rationale This TIP is related to discussions about [[457]](457.md) and the **-upvar** extended argument specifier. Adding an intropsection command to get the name of the variable linked to is more Tcl-ish than automatically adding a local variable with the linked name. The proposed command is not restricted to [[457]](457.md) usage as this can also be used for a link variable created by other means, using the **upvar** command for example. # Specification of the Proposed Change There should be a new subcommand of **info** created with the following syntax: > **info linkedname** _varname_ The _varname_ should be the name of a variable that has been linked to another variable \(e.g., with **upvar**, **global**, **variable** or **namespace upvar**\), and the result of the command will be the name of the variable linked to. # Reference Implementation The reference implementation is available in the info-linkedname <http://core.tcl.tk/tcl/timeline?r=info-linkedname> branch. The code is licensed under the BSD license. ## Implementation Notes Depending on the linked variable, the name is found using different methods: * The name of a variable present in a hash table \(globals, local variables created at runtime, ...\) is retrieved using the hash key; * The name of an array element is built using the name of the array and the index name, retrieved using the hash key. A new field is added to the TclVarHashTable sructure to access the related array variable from the array element; * The name of a compiled local variable is searched in current or upper call frames. # Copyright This document has been placed in the public domain. |
Name change from tip/472.tip to tip/472.md.
|
| < | < | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 472: Add Support for 0d Radix Prefix to Integer Literals Author: Venkat Iyer <[email protected]> Author: Brian Griffin <[email protected]> State: Accepted Type: Project Vote: Done Created: 25-May-2017 Post-History: Tcl-Version: 8.7 ----- # Abstract This TIP proposes adding support for a **0d** decimal radix prefix to complement the existing **0x** hexidecimal, **0o** octal and **0b** binary radix prefixes. # Rationale Verilog \(and other Hardware Description Languages\) always \(or at least since the 1995 LRM\) had a way to specify a decimal number explicitly. Verilog uses **'d343534** to mean decimal, VHDL actually allows any radix from 2 to 16 using syntax, so you could explicitly force a decimal interpretation using **10\#343534\#**. Tcl now allows **0b** for binary in **expr** and **format**, which is similar to **'b** in Verilog. And of course the **0x** prefix has always been around. Another use case would be to prevent false parsing of leading zeroes in **clock format**s as octal, without having to go through a **scan**. But a more elegant reason is that it makes the radix definition consistent, so 1. all valid input radixes have a consistent unambiguous input literal format, and 2. the **d** in **format %d** finally finds its complement in **scan**. # Specification Extend the **TclParseNumber** function to recognize the prefixes **0d** and **0D** as decimal integers. It will have the same semantics as **0x**, but base 10 instead of base 16. Also extend format command '\#' flag to produce the appropriate "0d" for the "%\#d" conversion. # Examples It's an integer: % expr {0d12 + 0d15} 27 % format "%#x" 0d1024 0x400 % format "%#d" 128 0d128 Errors same as other radix prefixes: % expr { 0d317g } invalid bareword "0d317g" in expression " 0d317g "; should be "$0d317g" or "{0d317g}" or "0d317g(...)" or ... % expr { 0x1.53 } missing operator at _@_ in expression " 0x1_@_.53 " % expr {0d7.23} missing operator at _@_ in expression "0d7_@_.23" # Compatibility Currently, literals beginning with **0d** and parsed as a number will produce an error. Any code expecting such an error would fail to produce an error an thus have a change in behavior. I would expect this situation to be uncommon. # Implementation An implementation can be found the fossil on the "bsg-0d-radix-prefix" branch, including %\#d conversion support. # Copyright This document has been placed in the public domain. |
Name change from tip/473.tip to tip/473.md.
|
| < | | | | | | < | | | > | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 473: Allow a Defined Target Namespace in oo::copy State: Final Type: Project Tcl-Version: 8.6.7 Vote: Done Post-History: Author: Donal Fellows <[email protected]> Created: 06-Jun-2017 Keywords: Tcl, missing functionality, bugfix ----- # Abstract This TIP adds functionality to **oo::copy** to allow the created copy to have a defined namespace, much as **oo::class**'s **createWithNamespace** method allows such a namespace to be given on normal object creation. # Rationale Due to an oversight, the **oo::copy** command is missing the ability to have an explicit namespace name specified to use as the instance namespace of the target object. It was always intended to have this \(and the functionality is there in the C API\), but it was omitted from the Tcl-level interface. Having this capability allows objects to be used as factories for namespaces, which is in many ways an inversion of the way that TclOO was designed \(with namespaces as the basis for objects\). It was requested by Nathan Coulter as a way to enable more complex behaviour in Rivet and NaviServer. See Tcl Issue dd3b844fda <http://core.tcl.tk/tcl/tktview/dd3b844fdabdeae5fcb0> for more information. # Proposed Change I propose to add one more optional argument to **oo::copy**, _targetNamespace_, that if provided and non-empty will be the name of a namespace \(resolved relative to the current namespace if not an absolute name\) that will be the name of the newly created target object's instance namespace. The named namespace must not already exist. Note that specifying the _targetObject_ as the empty string will cause the object's command to be automatically chosen. > **oo::copy** _sourceObject_ ?_targetObject_? ?_targetNamespace_? The meaning of the result of the command is unchanged. # Implementation See the oo-copy-ns branch. <http://core.tcl.tk/tcl/timeline?r=oo-copy-ns> # Copyright This document has been placed in the public domain. |
Name change from tip/48.tip to tip/48.md.
|
| < | < | | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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 | # TIP 48: Tk Widget Styling Support Author: Frédéric Bonnet <[email protected]> Author: Frédéric Bonnet <[email protected]> State: Final Type: Project Vote: Done Created: 23-Jul-2001 Post-History: Discussions-To: news:comp.lang.tcl Tcl-Version: 8.4 ----- # Abstract The Tk Toolkit is one of the last major GUI toolkits lacking themes support. This TIP proposes several changes to widget design that allows custom code to be provided for widget element handling in a transparent and extensible fashion. User-provided code may then be used to alter the widgets' look without the need to alter the Tk core. The proposed changes induce no loss of compatibility, and only slight core changes are needed with no side effect on existing functionality. # Background The Tk Toolkit appeared on X-Window systems at a time where Motif was the _de facto_ standard for GUI development. It thus naturally adopted Motif's look&feel and its famous 3D border style. First ports to non-X platforms such as Windows and MacOS kept the Motif style, which disappointed many users who felt Tk applications look "foreign". Version 8.0 released around 1996 added native look&feel on these platforms. Recently, other Open Source toolkits such as Qt \(used by the KDE project\) and GTK \(used by the GIMP graphics editing software and the Gnome project\) emerged as powerful and free alternatives to Motif for X-Window GUI development. The rapidly growing success of Open Source systems such as GNU/Linux helped both toolkits attract a vast community of developers, and the firm \(and sometimes friendly\) competition between both communities led to an explosion of new features. Thirst for freedom and customizability created the need for themeability. The current implementation of Tk only provides native look&feel on supported platforms \(Windows, X-Window, MacOS\). This lack partly explains Tk's loss of mind-share, especially amongst Linux developers, where theme support is considered a "cool" or must-have feature. While yesterday's goal of many GUIs was cross-platform visual uniformity \(Qt and GTK borrowed much of their visual appearance from Windows, which borrowed earlier from NeXTStep\), it is now quite common to find huge visual differences on today's desktops, even on similar systems. Screenshot contests are quite common nowadays. # Rationale Tk first kept away from the toolkit war. Tk's and its competitors' philosophies are radically opposite. Tk favors high level abstractions and scripting languages such as Tcl, whereas Qt and GTK developments are primarily done using C or C\+\+ \(which Tcl/Tk advocates believe to be The Wrong Way\). But despite Tk's power, flexibility and ease of use, it has lost serious mind-share, especially amongst newcomers and Linux users who don't care about its cross-platform capabilities. Many Tk users may see themes support as cosmetic or of lower importance than much needed features such as megawidgets or objectification. Nevertheless, this is a critical feature to be implemented for the long-term viability of Tk. Many courses are now promoting Qt, GTK or \(aarggg!\) Swing in place of Motif, leaving no room for Tk. Whatever its qualities \(cross-platform, performance, ease of use, internationalization and Unicode support\), the lack of themeability will always be seen as one of the main reasons for not using Tk. Applications using Tk instead of GTK will look as "foreign" on pixmap-themed Linux desktop, or even on newer MacOS and Windows versions, as pre-8.0 applications were on non-X desktops. The lack of themeability is neither a fatality nor difficult to solve. Tk already allows colors, fonts and border width and relief to be specified for all widgets. What is currently missing is pixmap themeing and border styles. The current proposal describes the required building blocks for theme support that are both easy to implement and backward compatible. A straightforward solution would be the one introduced by the Dash-patch in the form of new widget options such as _-tile_. This approach suffers from several major drawbacks: * A lot of new options are needed to handle the many ways of drawing pixmap tiles, such as anchoring, repeating, or scaling. * With the introduction of new options such as _-activebackground_, tile-related options must be duplicated for each widget state \(normal, active, disabled...\), thus cluttering the options namespace more and thus raising the learning curve. * Applying a theme to a whole widget hierarchy implies traversing the whole tree and applying a lot of options to each widget. * Memory consumption is increased for all widgets, even in the case when these options are not used. Moreover, one of the main goals of a theme being to enforce overall visual consistency, multiplying new options should be avoided. A theme is designed to gather these options into one place so that they can be shared by numerous widgets while avoiding performance or memory hit. A carefully designed theme engine should then only add one new option per widget to set its _style_ \(an essential part of a theme\). How far should themeabitily go? A previous version of this document proposed to extend the current 3D border mechanism to allow custom drawing code. Although this proposal was simple, backward compatible and covered most of the needs for themeability \(border style often represents the largest part of the visual appearance\), it failed to address other significant parts of the user interface. These include radio and check marks, scrollbar arrows, sliders, and other widget _elements_. From this point of view, the border is only an _element_ of a widget. A complete theme engine should then allow each UI element to be customized, while maximizing code reuse and preserving compatibility. To suit this model, widgets should then be thought of as assembly of elements, and no more as monolithic constructs. This implies a paradigm shift in the way widgets are _designed_ \(but not necessarily in the way they are _used_\). Actually, the notion of _element_ is not foreign to Tk, since some widgets \(scrollbars\) use the same term to identify their subparts. # A quick look at existing implementations The two major toolkits supporting widget styles are Qt and GTK\+. Both seem to follow the same path, but in slightly distinct manners: they define a fixed set of common elements \(arrows, checkmarks...\) and associate each with one or several API calls. While Qt follows the OO-path, GTK\+ uses a more traditional procedural API model. Qt defines a generic _QStyle_ class which is the base class for all styles \(Windows, Motif...\). QStyle-derived classes implement a number of virtual member methods, each being used to draw or compute the geometry of the many elements. Thanks to polymorphism, widgets can then use any style derived from this base class. Contrary to the C\+\+ -based Qt that defines a class gathering all style-related methods, GTK\+ is C-based and defines individual procedures \(e.g. _gtk\_draw\_slider_\). But overall, both use the same model: a predefined \(albeit potentially extensible\) set of elements, and associated overloadable methods/procs. Adding new elements implies recompilation and/or code changes. While it is hardly seen as a problem with Qt and GTK\+, since both target C/C\+\+ programming, it doesn't fit the Tcl/Tk model at all. # Proposal \(or There Must Be A Better Way\) This document describes a generic and extensible element handling mechanism. This mechanism allows elements to be created and/or overloaded at run-time in a modular fashion. Widgets are composed of elements. For instance, a scrollbar is made out of arrows, a trough, and a slider. Each element must be declared |
︙ | ︙ | |||
166 167 168 169 170 171 172 | Elements are declared along with an implementation. This declaration can be made by the system or by widgets themselves, and at run-time, thus allowing extensions to create new and use or derive existing elements. Implementations are registered in a given style engine. A style engine is thus a collection of element implementations. Style engines | | | | | | | | 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 | Elements are declared along with an implementation. This declaration can be made by the system or by widgets themselves, and at run-time, thus allowing extensions to create new and use or derive existing elements. Implementations are registered in a given style engine. A style engine is thus a collection of element implementations. Style engines can be declared at run-time as well, but are static \(since they provide compiled code\). Style engines can be layered in order to reuse and redefine existing elements implementations, falling back to the default, core-defined engine. A style is an instance of a style engine. Styles can be given client data information that would carry style engine-specific data. For example, a style engine implementing pixmapped elements could be given the pixmaps to use. Styles can be created and deleted at run-time. Using this scheme, a widget can register elements and their default implementation, but actually use a custom implementation code in a transparent manner depending on its currently applied style. Moreover, elements can be shared across widgets, new elements can be registered dynamically and used transparently. New widgets could also be built in a modular fashion and easily reuse other widget's elements. The proposed mechanism could then be used in a megawidget-like fashion \(we could speak about megaelement widgets\). Last, it provides a dynamic hook mechanism for overriding the core widget code from loadable extensions, avoiding the need for maintaining core patches. # Functional Specification Style engines: Style engines gather code for handling a set of elements. For this reason, they are inherently static, alike _Tcl\_ObjType_s. They can be registered at run-time, queried, but never unregistered, since external style engines will usually be provided by loadable packages, and that Tcl does not support library unloading. Styles: Styles are instances of style engines. While engines are static, styles can be dynamic. All styles of the same engine use the same code for handling elements, but using different data provided at creation-time. For example, a generic pixmap engine may be instantiated by several styles providing a different set of pixmaps. Styles can be created at run-time, queried, and freed. Since they are user-visible entities, a _Tcl\_Obj_-based interface is also provided. Elements: Elements are virtual entities. An element only exists if an implementation has been provided. Thus, elements are created implicitly. They can be queried, but not destroyed. Upon creation, elements are given a unique ID that remains valid for the entire application life time and is used subsequently for all related calls. It serves as a numerical |
︙ | ︙ | |||
229 230 231 232 233 234 235 | also provide a list of required widget options. Elements would then pick the option values from the widget record according to the widget's option table. In the case when the desired option is missing from the option table, the element would have to either try other options of fail gracefully and use sensible default values. | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 | also provide a list of required widget options. Elements would then pick the option values from the widget record according to the widget's option table. In the case when the desired option is missing from the option table, the element would have to either try other options of fail gracefully and use sensible default values. # Detailed Specification The proposal introduces a set of new public types and APIs, exported from _generic/tk.h_ and the stubs table. The implementation induces very slight and limited changes to the existing code, with only one new private API added \(_TkGetOptionSpec_ in _generic/tkConfig.c_\). Most of the new code is concentrated into one file. There is no side effect on existing functionality. _Types and constants_. TK\_OPTION\_STYLE: New _Tk\_OptionType_ usually associated with the _-style_ widget option. TK\_STYLE\_VERSION\_1, TK\_STYLE\_VERSION: Version numbers of Tk style support. The former matches the implementation described in this proposal. The latter is a shortcut to the current version. Future extensions may introduce new version numbers. Tk\_StyleEngine: Opaque token for handling style engines. May be NULL, meaning the default system engine. Tk\_StyledElement: Opaque token holding a style-specific implementation of a given element. Subsequently used for performing element ops. Tk\_Style: Opaque token for handling styles. May be NULL, meaning the default system style. Tk\_GetElementSizeProc, Tk\_GetElementBoxProc, Tk\_GetElementBorderWidthProc, Tk\_DrawElementProc: Implementations of various element operations. typedef void (Tk_GetElementSizeProc) _ANSI_ARGS_((ClientData clientData, char *recordPtr, CONST Tk_OptionSpec **optionsPtr, Tk_Window tkwin, int width, int height, int inner, int *widthPtr, int *heightPtr)); typedef void (Tk_GetElementBoxProc) _ANSI_ARGS_((ClientData clientData, char *recordPtr, CONST Tk_OptionSpec **optionsPtr, Tk_Window tkwin, int x, int y, int width, int height, int inner, int *xPtr, int *yPtr, int *widthPtr, int *heightPtr)); typedef int (Tk_GetElementBorderWidthProc) _ANSI_ARGS_((ClientData clientData, char *recordPtr, CONST Tk_OptionSpec **optionsPtr, Tk_Window tkwin)); typedef void (Tk_DrawElementProc) _ANSI_ARGS_((ClientData clientData, char *recordPtr, CONST Tk_OptionSpec **optionsPtr, Tk_Window tkwin, Drawable d, int x, int y, int width, int height, int state)); Tk\_ElementOptionSpec: Used to specify a list of required widget options, along with their type. This info will be subsequently used to get option values from the widget record using its option table. typedef struct Tk_ElementOptionSpec { char *name; Tk_OptionType type; } Tk_ElementOptionSpec; Tk\_ElementSpec: Static styled element definition. The version field must be set to TK\_STYLE\_VERSION\_1 in order to match the following structure. typedef struct Tk_ElementSpec { int version; char *name; Tk_ElementOptionSpec *options; Tk_GetElementSizeProc *getSize; Tk_GetElementBoxProc *getBox; Tk_GetElementBorderWidthProc *getBorderWidth; Tk_DrawElementProc *draw; } Tk_ElementSpec; TK\_ELEMENT\_STATE\_\*: Flags used when drawing elements. Elements may have a different visual appearance depending on their state. However, it should be noted that the element size is not affected by state changes. #define TK_ELEMENT_STATE_ACTIVE (1<<0) #define TK_ELEMENT_STATE_DISABLED (1<<1) #define TK_ELEMENT_STATE_FOCUS (1<<2) #define TK_ELEMENT_STATE_PRESSED (1<<3) _Functions_. TkStylePkgInit, TkStylePkgFree: Internal procedures used to initialize the style subpackage on a per-application basis. void TkStylePkgInit (TkMainInfo *mainPtr) void TkStylePkgFree (TkMainInfo *mainPtr) TkGetOptionSpec: Internal function used to retrieve an option specifier from a compiled option table. CONST Tk_OptionSpec * TkGetOptionSpec (CONST char *name, Tk_OptionTable optionTable); Tk\_RegisterStyleEngine: Registers a new style engine. Tk_StyleEngine Tk_RegisterStyleEngine (char *name, Tk_StyleEngine parent) > Name may be NULL, in which case it registers the default engine. Returns a NULL token if an error occurred \(e.g. registering an existing engine\). Tk\_GetStyleEngine: Returns a token to an existing style engine, or NULL. Tk_StyleEngine Tk_GetStyleEngine (char *name) Tk\_RegisterStyledElement: Registers the implementation of an element for a given style engine. int Tk_RegisterStyledElement (Tk_StyleEngine engine, Tk_ElementSpec *templatePtr) > Element names use a dotted notation that gives a hierarchical search order. For example, a widget requiring an element named "Scrollbar.vslider" can actually use the "vslider" generic element. Apart from this dotted notation, element names are free-form. However, conventions should be defined, such as capitalized widget classes, and lower case elements. Since whole widgets can act as elements, one can therefore register an element named "Scrollbar". > The given pointer is not stored into internal structures, but is instead used to fill them. Styled element specs can thus be allocated on the stack or dynamically, but in most cases they will be statically defined. Tk\_GetElementId: Returns the unique numerical ID for an already registered element. int Tk_GetElementId (char *name) Tk\_CreateStyle: Creates a new style as an instance of an existing style engine. Tk_Style Tk_CreateStyle (CONST char *name, Tk_StyleEngine engine, ClientData clientData) > Client data may be provided, that will be passed as is to element operations. Tk\_GetStyle: Retrieves an existing style by its name. Tk_Style Tk_GetStyle (Tcl_Interp *interp, CONST char *name) > Retrieves either an existing style by its name, or NULL if none was found. In the latter case, leaves an error message in _interp_ if it is not NULL. Tk\_FreeStyle: Frees a style returned by _Tk\_CreateStyle_ or _Tk\_GetStyle_. void Tk_FreeStyle (Tk_Style style) > It actually decrements an internal reference count so that styles can be shared and deleted safely. Tk\_NameOfStyle: Gets a style's name. CONST char * Tk_NameOfStyle (Tk_Style style) Tk\_AllocStyleFromObj, Tk\_GetStyleFromObj, Tk\_FreeStyleFromObj: _Tcl\_Obj_ based interface to styles. Tk_Style Tk_AllocStyleFromObj (Tcl_Interp *interp, Tcl_Obj *objPtr) Tk_Style Tk_GetStyleFromObj (Tcl_Obj *objPtr) void Tk_FreeStyleFromObj (Tcl_Obj *objPtr) > _Tk\_AllocStyleFromObj_ gets \(doesn't create\) an existing style from an object. _Tk\_GetStyleFromObj_ returns the style already stored in the object's internal representation. The object must have been returned by _Tk\_AllocStyleFromObj_. _Tk\_FreeStyleFromObj_ frees the style held by the object. Tk\_GetStyledElement: Returns a token for the styled element for use with widgets having the given _optionTable_. Tk_StyledElement Tk_GetStyledElement (Tk_Style style, int elementId, Tk_OptionTable optionTable) > Returns a token for the styled element \(or NULL if not found\), for use with widgets having the given optionTable. The token is persistent and doesn't need to be freed, so it can be safely stored if needed \(although using element IDs is the preferred method\). It is used in subsequent element operations and avoids repeated lookups. The lookup algorithm works as follows: > 1. Look for an implementation of the given element in the current style engine. > 2. If none was found, traverse the chain of engines \(each but the default engine has a parent\) until the default engine is reached. > 3. Restart at step 1 with the base element name instead. For example, if we are looking for "foo.bar.baz", then look for "bar.baz" then "baz", until we find an implementation. > If no implementation was found, then a panic is generated, meaning that some dependency has not been resolved. In the general case, this won't happen for core widgets \(because they only use core elements\), and new widgets either have to rely on core or package-provided elements, or define their own. Tk\_GetElementSize, Tk\_GetElementBox, Tk\_GetElementBorderWidth, Tk\_DrawElement: Various element operations. void Tk_GetElementSize (Tk_Style style, Tk_StyledElement element, char *recordPtr, Tk_Window tkwin, int width, int height, int inner, int *widthPtr, int *heightPtr) void Tk_GetElementBox (Tk_Style style, Tk_StyledElement element, char *recordPtr, Tk_Window tkwin, int x, int y, int width, int height, int inner, int *xPtr, int *yPtr, int *widthPtr, int *heightPtr) int Tk_GetElementBorderWidth (Tk_Style style, Tk_StyledElement element, char *recordPtr, Tk_Window tkwin) void Tk_DrawElement (Tk_Style style, Tk_StyledElement element, char *recordPtr, Tk_Window tkwin, Drawable d, int x, int y, int width, int height, int state) > The first two are used for geometry management. First one only computes the size, while second one computes the box coordinates. The _inner_ parameter is a boolean that controls whether the inner \(FALSE\) or outer \(TRUE\) geometry is requested from the maximum outer/minimum inner geometry. Third one returns the uniform internal border width of the element and is mostly intended for whole widgets. Last one draws the element using the given geometry and state. # Implementation An implementation has been written and completed with respect to the present specification. A patch for Tk 8.4a3 is available at: > <http://www.purl.org/NET/bonnet/pub/style.patch> The _square_ widget implemented in the test file _generic/tkSquare.c_ has also been rewritten to use the new API for its square element. It demonstrates basic features. Patch file: > <http://www.purl.org/NET/bonnet/pub/squarestyle.patch> The sample code registers an element "Square.square" in the default style engine. This element is used by the square widget in its drawing code. A new style engine "fixedborder" is registered, and code is provided for the "Square.square" element. This style engine draws the element's border using a fixed border width given as client data by instantiated styles. Four styles are created as instances of the "fixedborder" element: "flat", "border2", "border4" and "border8" \(0, 2, 4 and 8 pixel-wide borders\). Sample test session: pack [square .s] .s config -style .s config -style flat .s config -style border2 .s config -style border4 .s config -style border8 .s config -style "" pack [square .s2] .s2 config -style border2 .s2 config -style border8 # Performance and memory usage The provided design and implementation is geared towards the best compromise between performance and memory consumption. Critical performance bottleneck is element querying. In order to minimize element access times, elements are identified by unique IDs that act as indexes within internal tables, allowing direct addressing. Hash tables are used internally by all name pools \(engines, styles, elements\). Static structures are used whenever possible \(for styled element registration, indirectly through widgets' option tables...\). Widget processing times are increased by the extra procedure calls and indirections, but that is the price to pay for better modularity anyway. Additional calls are kept minimal. Per-widget memory consumption is minimal. A widget usually only needs to store its current style. Element IDs can \(should?\) be shared globally across widgets of the same class and don't need to be stored in the widget record. Moreover, most information is shared internally across widgets of the same class \(identified by their option table\). Many caching & fast lookup techniques are used throughout the code. # Compatibility Existing widgets will need to be rewritten in order to become style-aware. The required code changes may be significant \(implying code modularization\). However, no incompatibility is introduced. Thus, migrating widgets from the old to the new model can follow a smooth path, similar to that needed for the transition to _Tcl\_Obj_ interfaces. Besides, widgets as a whole can act as elements, which may shift the amount of work from the core to the style engines at the expense of a lesser modularity and code reuse. # Future improvements or changes * Additional APIs for querying the list of engines, styles, elements... * Additional operations for elements, e.g. hit tests. * Script-level interfaces. * Optional translation tables between real widget options and needed element options, e.g. _-elementborderwidth_ => _-borderwidth_. * How to handle native widgets? They will certainly have to be provided as whole elements. * Current implementation uses thread-local storage for holding dynamic data. Since most data is not thread-specific, this could be changed to a more memory-efficient scheme. * Provide man pages and tests. * Additional hidden/private option flag for accessing some widgets' non-configurable data \(e.g. scrollbar position\) through option tables. # Glossary Element: Part of a widget \(e.g. a checkbox mark or a scrollbar arrow\), usually active. Style: The visual appearance of a widget. May include colors, skins, tiles, border drawing style \(Windows, Motif...\), element pictures. Styled element: A style-specific implementation of a widget element. Style engine: A visually consistent collection of styled elements. Theme: A collection of graphical elements giving a consistent appearance to a whole widget hierarchy, application, or desktop. A theme is usually made up out of icons, colors, fonts, widget styles, or even desktop background and sounds. # Copyright This document has been placed in the public domain. |
Name change from tip/49.tip to tip/49.md.
|
| < | < | | | | | | | > | | | | | | | | | | | | | | | | | | | | | < > | < > | | < > | | | < > | | < > | | | | | | < > | | | | | | | | | < > | | | | | < > | < > | | > | 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 | # TIP 49: I/O Subsystem: Add API Tcl_OutputBuffered(chan) Author: Rolf Schroedter <[email protected]> State: Final Type: Project Vote: Done Created: 25-Jul-2001 Post-History: Tcl-Version: 8.4 ----- # Abstract This document proposes the new public function _Tcl\_OutputBuffered\(\)_, analogous to the existing public function _Tcl\_InputBuffered\(\)_. # Rationale Tcl has a _Tcl\_InputBuffered\(\)_ function but no analog function for the output buffer. A _Tcl\_OutputBuffered\(\)_ function would be useful for non-blocking channel drivers which need to know the number of bytes pending in Tcl's output queue. The implementation of [[35]](35.md) allows one to query the number of bytes in the channels input and output queues with a _[fconfigure -queue]_ option. This is a useful feature especially for serial ports because the input/output may be really slow or even stall. On the driver level only the number of bytes in the system queue can be queried. For a non-blocking channel there may also be some pending output in Tcl buffers. Obviously there is not much sense to know only the byte counter at driver level without knowing _Tcl\_OutputBuffered\(\)_. # Related Ideas It could also be useful to add general _[fconfigure -inputbuffer -outputbuffer]_ options for all channels returning the values from _Tcl\_InputBuffered\(chan\)_ and _Tcl\_OutputBuffered\(chan\)_ respectively. At this opportunity the code of _Tcl\_Seek\(\)_ and _Tcl\_Tell\(\)_ may be shortened, because it repeats the code of _Tcl\_InputBuffered\(\)_ and _Tcl\_OutputBuffered\(\)_. # Implementation This function would be added to _generic/tclIO.c_ and be stubs enabled. This new API should not have any impact on existing applications. The implementation is analog to what is done in _Tcl\_Tell\(\)_: /* *---------------------------------------------------------------------- * * Tcl_OutputBuffered -- * * Returns the number of bytes of output currently buffered in the * common internal buffer of a channel. * * Results: * The number of output bytes buffered, or zero if the channel is not * open for writing. * * Side effects: * None. * *---------------------------------------------------------------------- */ int Tcl_OutputBuffered(chan) Tcl_Channel chan; /* The channel to query. */ { ChannelState *statePtr = ((Channel *) chan)->state; /* State of real channel structure. */ ChannelBuffer *bufPtr; int bytesBuffered; for (bytesBuffered = 0, bufPtr = statePtr->outQueueHead; bufPtr != (ChannelBuffer *) NULL; bufPtr = bufPtr->nextPtr) { bytesBuffered += (bufPtr->nextAdded - bufPtr->nextRemoved); } if ((statePtr->curOutPtr != (ChannelBuffer *) NULL) && (statePtr->curOutPtr->nextAdded > statePtr->curOutPtr->nextRemoved)) { statePtr->flags |= BUFFER_READY; bytesBuffered += (statePtr->curOutPtr->nextAdded - statePtr->curOutPtr->nextRemoved); } return bytesBuffered; } # Copyright This document has been placed in the public domain. |
Name change from tip/5.tip to tip/5.md.
|
| < | < | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | < > | | | | < > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | < > | | | | | | | | | | | | | < > | | | | | | | < | > | | | | | | | | | | | | | | | | | | | | | | | | > | 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 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 | # TIP 5: Make TkClassProcs and TkSetClassProcs Public and Extensible Author: Eric Melski <[email protected]> State: Final Type: Project Tcl-Version: 8.4 Vote: Done Created: 17-Oct-2000 Post-History: ----- # Abstract At certain critical moments in the lifetime of a Tk widget, Tk will invoke various callbacks on that widget. These callbacks enable the widget to do lots of interesting things, such as react to configuration changes for named fonts, or create and manage truly native widgets \(such as the scrollbar widget on Windows platforms\). The API for setting up these callbacks for a particular window are, as of Tk 8.3.2, private. This prohibits extension widget authors from fully utilizing this powerful system; those developers can either copy the private declarations into their own source code \(leading to future maintenance hassles\), or forego the system entirely, hampering their ability to make truly native and well-integrated widgets. This proposal offers an extensible means for making that API public. # Rationale: Why make TkClassProcs and TkSetClassProcs public? \(The following text is adapted from George Howlett <http://dev.scriptics.com/lists/tclcore/2000/10/msg00143.html> \) The Tk toolkit was originally written strictly for Xlib. It created wrappers for many of the Xlib calls. A good example is creating a window. Tk's _Tk\_CreateWindow_ call in turn calls Xlib's _XCreateWindow_. This is so that the toolkit can perform bookkeeping on the window and manage it in various ways. The down side was that if you needed to pass specific information/flags to the _XCreateWindow_ call you couldn't. But this only affected extensions. Now when Tk 8.0 added native widgets, Tk also had the same problem. For example to create a Win32 button control, you have to pass information through the X emulation layer to the eventual Win32 CreateWindow or CreateWindowEx call. So the Sun Tk developers created this notion of class procedures. A widget of particular type may need to make different calls at the time the window is created. They added to the TkWindow structure pointers to both the widget instance \(i.e. the data the represents the specific widget\) and a structure of function pointers \(such as one to call when the window is to be created\). TkClassProcs tkpButtonProcs = CreateProc, /* createProc. */ TkButtonWorldChanged, /* geometryProc. */ NULL /* modalProc. */ }; Inside of Tk, such as in _Tk\_MakeWindowExist_, code was added to check if the _createProc_ of the structure isn't NULL and call that routine to create the native window. This mechanism was also used to handle font aliasing. I can create a font "fred" that is really a \{ courier bold \} font and use it with any Tk widget. font create fred -family courier -weight bold button .b -font fred The widget will get the real font and use it in its graphics context. Think of GCs like a pen drawing a particular color. A GC draws with a particular font. Now if I change the font, the widget's GC must be updated too. font create fred -family helvetica -weight medium You can see where a _geometryProc_ is needed to indicate when font aliases change. It gets called for all the widgets using the font. Another callback is used to handle modal events. This is currently needed only for the Win32 native scrollbar. So here's the private structure and _TkSetClassProcs_ call. typedef Window (TkClassCreateProc) _ANSI_ARGS_((Tk_Window tkwin, Window parent, ClientData instanceData)); typedef void (TkClassGeometryProc) _ANSI_ARGS_((ClientData instanceData)); typedef void (TkClassModalProc) _ANSI_ARGS_((Tk_Window tkwin, XEvent *eventPtr)); /* * Widget class procedures used to implement platform specific widget * behavior. */ typedef struct TkClassProcs { TkClassCreateProc *createProc; /* Procedure to invoke when the platform-dependent window needs to be created. */ TkClassGeometryProc *geometryProc; /* Procedure to invoke when the geometry of a window needs to be recalculated as a result of some change in the system. */ TkClassModalProc *modalProc; /* Procedure to invoke after all bindings on a widget have been triggered in order to handle a modal loop. */ } TkClassProcs; void TkSetClassProcs(tkwin, procs, instanceData) Tk_Window tkwin; /* Token for window to modify. */ TkClassProcs *procs; /* Class procs structure. */ ClientData instanceData;/* Data to be passed to class procedures. */ { register TkWindow *winPtr = (TkWindow *) tkwin; winPtr->classProcsPtr = procs; winPtr->instanceData = instanceData; } Extension developers could not use this interface, however, because it was private to Tk. The original authors of the interface didn't think that anything outside of the Tk widgets would need it. Of course, hindsight is 20-20, and we have since found that this is not true. Extension developers do need to use this system: widget writers that use fonts obviously need to know when a font alias changes, and new Win32 native widgets also need access to this mechanism. Most extensions authors had/have already found a workaround: copy in the _TkClassProcs_ structure and _TkSetClassProcs_ routine into your code. However, this workaround leads to future code maintenance problems. Because the structure is private, its members and usage are not guaranteed to remain constant between versions of Tk. If the structure changes, the extension authors have to update all of their code accordingly. Making the system public locks in the format and usage of the system, so that extension authors can rely on it existing from one version to the next, and they will no longer have to maintain parallel redundant copies of the structure and function definition. # Rationale: Why make TkClassProcs and TkSetClassProcs extensible? Every time we've made a public structure, we've regretted it later when we needed to extend it to handle some new feature that we didn't originally anticipate. In general we should avoid designing new API's that preclude making future changes without introducing incompatibilities. <http://dev.scriptics.com/lists/tclcore/2000/10/msg00083.html> This system is one that seems likely to require extension in the future. There are currently three callbacks: create window, geometry change, and modal event. Already one request to extend the mechanism has been made, to support the notion of a "client area" related to geometry management and labelled frame widgets \(<http://dev.scriptics.com/lists/tclcore/2000/10/msg00121.html> , <http://dev.scriptics.com/lists/tclcore/2000/10/msg00170.html> \). Another possible extension is a focus management callback, to allow for smoother focus transitions between native widgets and Tk widgets; note that this focus management callback is a purely hypothetical extension at this time. If the system is one that we are likely to want to extend with additional callbacks in the future, it behooves us to make it public in a manner that allows us to extend it while causing the minimum amount of disruption for extension authors. There are two concerns here. First is binary compatibility: will an extension compiled against a version of Tk which features the base \(three callback\) _TkClassProcs_ system work with a version of Tk that features an extended _TkClassProcs_ system? Second is source compatibility: will an extension author have to update their sources when they want to recompile their extension against a version of Tk that features an extended _TkClassProcs_ system? Ideally, the system that we make public will allow extension while retaining binary and source compatibility between versions of Tk. # Specification I propose that the following steps be taken to make _TkClassProcs_ and _TkSetClassProcs_ public: 1. Rename _TkClassProcs_ to _Tk\_ClassProcs_; rename _TkSetClassProcs_ to _Tk\_SetClassProcs_; rename _TkClassCreateProc_, etc., to _Tk\_ClassCreateProc_, etc. Move the structure definition, function prototype, and callback typedefs from tkInt.h to tk.h. This is in keeping with Tk public interface naming conventions. 2. Add a single size field to the _Tk\_ClassProcs_ structure. This field is initialized at the time that the structure is allocated, and always contains the size of the structure. This field will be used to provide a simple versioning scheme for the structure. Portions of Tk that use the class proc callbacks will inspect this size field to ascertain whether or not a particular instance of the _Tk\_ClassProcs_ structure is of a version that contains a given callback. See the example below. 3. Rename the _geometryProc_ callback to _worldChangedProc_. The name _geometryProc_ is somewhat misleading. Currently, the callback is used only to support font aliasing, as described above. This is sort of geometry related, but it doesn't necessarily mean that geometry of the widget must change, it just means that the widget will have to update its world view to reflect the current state of the world. In addition, the callback will likely be used to support color aliasing when that is added to Tk \(imagine defining a color "myColor" to mean "\#c4d3a2" and then configuring widgets to use "myColor" instead of the literal value; this provides all the benefits for colors that font aliasing does for fonts\). When that is done, _geometryProc_ will be truly misleading, since a color change probably does not mean a geometry change for the widget. 4. Change the order of the callback fields in the _Tk\_ClassProcs_ structure, making _worldChangedProc_ the first of the callbacks listed in the structure. In the existing private _TkClassProcs_ structure, the first callback is the _createProc_. It is not strictly necessary to make _worldChangedProc_ the first callback. However, most widgets in Tk \(canvas, entry, scale, text, message, listbox, menu, menubuttons, scrollbars on Unix and Mac, and buttons on Unix and Mac\) use only this callback. Making it first in the structure \(after the size field, which must be the very first entry\) means a little bit less work for widget authors in the common case, because they need not include the NULL declaration for the _createProc_ slot in the structure. Compare: static Tk_ClassProcs myClassProcs = { sizeof(Tk_ClassProcs), NULL, myWorldChangedProc }; > with: static Tk_ClassProcs myClassProcs = { sizeof(Tk_ClassProcs), myWorldChangedProc }; > Since the _createProc_ is used so infrequently, why require that all widget authors explicitly declare it to be NULL? This change just simplifies everybody's life that much more. Usage of the public API will be very similar to usage of the existing private API: static Tk_ClassProcs myClassProcs = { sizeof(Tk_ClassProcs), myWorldChangedProc }; static int Tk_MyWidgetObjCmd(...) { ... Tk_SetClassProcs(widgetPtr->tkwin,myClassProcs,(ClientData)widgetPtr); ... return TCL_OK; } Portions of Tk that need to use a particular callback, such as _Tk\_MakeWindowExist_, use code like the following: Tk_ClassProcs *thisClassProcs = tkwin->classProcs; createProc *procPtr; /* Make sure the structure we were given has the createProc field * in it by checking that the size of the structure is at least * big enough to have that slot. */ if (thisClassProcs->size <= Tk_Offset(Tk_ClassProcs, createProc)) { procPtr = NULL; } else { procPtr = thisClassProcs->createProc; } if (procPtr != NULL) { /* Invoke the createProc for this window. */ ... } else { /* Use the default Tk window creation mechanism. */ ... } # Benefits of this implementation Benefits of this implementation are as follows: 1. Usage of _Tk\_ClassProcs_ and _Tk\_SetClassProcs_ very, very closely parallels the usage of the existing private API. In fact, the only difference is a small change in the particular fields of the _Tk\_ClassProcs_ structure \(especially, the new size field, for version information, and the reordering of the callback fields\). 2. All instances of "mywidget" reference the same _Tk\_ClassProcs_ structure. This is memory efficient. 3. We do not need to explicitly initialize to NULL those fields of myClassProcs that we don't use. The ANSI C specification states that static variables \(and members of statically declared structures\) that are not explicitly initialized are initialized to zero. 4. This retains binary compatibility. The size field of the _Tk\_ClassProcs_ structure is set at compile time, so when a later version of Tk checks the size field to see if a new callback can be used, it will fail. That is, if extension author A compiles the extension against version X of Tk, which has three fields in _Tk\_ClassProcs_, the size field of myClassProcs will be set to 12 \(assuming 4-byte pointers\). When using that extension with Tk version Y, which may have four fields in _Tk\_ClassProcs_, the size check for that fourth field will fail, since the size field, set to 12, will be less than or equal to the offset of the fourth field in the structure. 5. This retains source compatibility. Because of \#3 above, unless the extension author wants to use the new callbacks, they need not worry about their addition, because the new fields will be automatically set to zero. 6. There is minimal API bloat. Only one public API is added, _Tk\_SetClassProcs_. 7. The system is "type safe" with respect to the function signatures of the callback functions. Any type mismatches will be caught at compile time. 8. If desired, widget authors can directly reference elements of the _Tk\_ClassProcs_ structure: myClassProcs.createProc = myCreateProc; # Drawbacks of this implementation The drawbacks of this implementation are as follows: 1. The required value of the size field will seem like a bit of black magic to developers new to the system. The question _"Why does this field have to be set to this value? If it's always the same thing, why is it stored at all?"_ Of course, experienced programmers will recognize why it has to be set, and that in fact, it is not always the same value. This issue can best be addressed by appropriate documentation. 2. Extensions that use the existing private _TkClassProcs_ and _TkSetClassProcs_ mechanism and which were compiled against versions of Tk <= 8.3 will not work with new versions of Tk, since the format of the _Tk\_ClassProcs_ structure will change. However, this is the consequence of using private structures and API's in your extensions: when those private structures and API's change, you have to update your extension accordingly. We cannot allow ourselves to be overly constrained by this issue. The existing mechanism is private, period. Authors that use it do so knowingly and willfully. # Reference Implementation <http://sourceforge.net/patch/?func=detailpatch&patch\_id=102213&group\_id=10894> # Copyright This document has been placed in the public domain. |
Name change from tip/50.tip to tip/50.md.
|
| < | < | | | | | | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 50: Bundle [incr Tcl] with the Core Tcl distribution Author: Kevin Kenny <[email protected]> Author: Mark Harrison <[email protected]> Author: Jeff Hobbs <[email protected]> Author: Andreas Kupries <[email protected]> Author: Karl Lehenbauer <[email protected]> Author: Michael McLennan <[email protected]> Author: Don Porter <[email protected]> Author: Brent Welch <[email protected]> State: Final Type: Informative Vote: Done Created: 27-Jul-2001 Post-History: ----- # Abstract A "town meeting" discussion in which users were given the opportunity to question the Tcl Core Team at the 2001 Open Source Convention has revealed a great popular demand for bundling an object system with the distribution of the Tcl Core. This TIP presents a compromise proposal for including [incr Tcl] that was acceptable to all eight TCT members present. # Proposal * [incr Tcl] <http://tcltk.com/itcl/> shall be bundled with the core Tcl distribution. * [incr Tcl] shall be "included" in the Core in only a weak sense. > The location of the [incr Tcl] source tree shall be left to the discretion of the affected maintainers. \(It appears likely that most [incr Tcl] source will appear in a separate _itcl_ directory parallel to the _generic_, _mac_, _unix_ and _win_ directories in the source.\) > [incr Tcl] shall be built as a separate loadable package, similar to the _dde_, _http_, _msgcat_, and _registry_ packages. > The _::itcl_ namespace shall be the only new component included in the global namespace, and shall appear only when a script executes package require Itcl > There shall be no _::class_ command in the Core. > The _::info_ command shall not provide any subcommands specific to [incr Tcl]. * [incr Tcl] shall not be substantially modified under the scope of this TIP. > The existing issues surrounding errors thrown from object destructors shall not be addressed. > The existing use of _rename_ for object destruction shall not be amended. > All other limitations of [incr Tcl] are initially accepted as they are. > Of course, additional TIPs could be submitted to modify [incr Tcl] as desired! * The TCT shall assume the role of _gatekeeper_ for changes to the functionality of [incr Tcl]. > Changes that affect user-visible functionality of [incr Tcl] shall be made through the TIP process. > Informational TIPs identifying maintainer areas and assigning maintainers to them shall be developed. * Nothing in this TIP shall be construed as identifying [incr Tcl] as a single preferred object system for Tcl. If the community desires other systems such as OTcl, XOTcl, or ObjecTcl to stand on an equal footing to [incr Tcl], their champions can introduce TIPs similar to this one. * [incr Tk] and [incr widgets] are outside the scope of this TIP. # Rationale The lack of a standard object and data abstraction system continues to hinder Tcl development. > "Lets face it, not including any sort of OO system is one of the major failings of Tcl. Indexing into global arrays is a sad hack when compared to a real OO system." _- Mo DeJong <[email protected]>_ Moreover, the argument that "Tcl is not object oriented" continues to hamper Tcl marketing. Including at least one object system with the Tcl core, so that it is dependably available unless the user has built from source, would address this objection. Since an earler proposal \([[6]](6.md)\) to incorporate [incr Tcl] into the Core failed to garner the necessary votes, at least in part because participants were uncertain of the rationales, it seems wise to discuss the individual points in further detail. * All agree that some sort of object system must be bundled with the core so that it is dependably available. [incr Tcl] appears to be the most popular of the existing systems, as well as the most familiar to the current TCT, making it the most attractive of several candidates for this role. * The original [incr Tcl] developers have pointed out that bundling in the Core would facilitate [incr Tcl] development greatly. While it is a separate loadable package, [incr Tcl] is intimate with the core, depending on many undocumented interfaces to carry out its functions. Integrating it with the Core would make it easier to maintain. * Including a _::class_ command in the Core is not acceptable at this time, because it would have the effect of disenfranchising the users of other object systems -- who are too numerous to ignore. Moreover, the ability of Tcl to serve as a test platform for novel object models must not be compromised. * Similarly, integrating [incr Tcl] closely with commands such as _::info_ or _::destroy_ would accord it a privileged status that the users of other object systems are reluctant to accept. * [incr Tcl] is what it is. It would be inappropriate to demand that all the perceived shortcomings of the [incr Tcl] system be addressed prior to inclusion in the Core. The TIP process is available to make further changes; the system is certainly good enough that many thousands of programmers use it daily. * If [incr Tcl] is to be included in the Core, then common sense requires that it be under control of the TIP process. # Alternatives * Include [incr Tcl] in a "batteries included" \(BI\) distribution. > Many people will not opt for the BI distribution \([[4]](4.md)\) due to its larger size. It is quite likely that \(for example\) a Linux distribution my include Tcl as a standard component, but place the BI on a supplemental disk. > Moreover, as mentioned above, the [incr Tcl] sources are already intimate with the Tcl core; there are great maintenance savings to be achieved by combining the source distributions. * Integrate [incr Tcl] tightly into the Tcl Core. > This alternative is unacceptable to a good many users. A number of attendees at the 2001 Open Source Convention mentioned specifically that they use alternative object systems such as OTcl. These users would be essentially disenfranchised if, for instance, a _::class_ command were to appear in the Core. # Implementation Jeff Hobbs has volunteered to lead the implementation effort with the assistance of all volunteers who want to help. # Notes Eight members of the Tcl Core Team \(Harrison, Hobbs, Kenny, Kupries, Lehenbauer, McLennan, Porter and Welch\) agreed orally to this proposal at the 2001 Open Source Convention. Since not all have had the opportunity to read the formal written version of the proposal, that vote shall not be considered binding. # References * <http://tcltk.com//itcl> * [[6]](6.md) # Copyright This document has been placed in the public domain. |
Name change from tip/51.tip to tip/51.md.
|
| < | < | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | < > | < > | | | | | | < > | | < > | | < > | | | | | | | | | < > | | | | | | | | | | | | | | | < > | | | | | | | | | | | | < > | | | | | | | < < < > > > | < < < > > > | | | | | < > | | < > | | < > | | | | < > | > | | 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 | # TIP 51: Native Menubutton on Macintosh Author: Mats Bengtsson <[email protected]> State: Withdrawn Type: Project Tcl-Version: 8.5 Vote: Pending Created: 04-Aug-2001 Post-History: ----- # Abstract This is a replacement for the menubutton on the Macintosh with a native implementation which is compliant with the Appearance Manager in Mac OS 8 and later. # Rationale The present \(in 8.3.3 and earlier\) menubutton on the Macintosh is implemented using Tk drawing to draw something similar to the native menubutton on Mac how it looks on Pre Mac OS 8.0 systems, and therefore fails to give the correct appearance on Mac OS 8.0 systems and later. This TIP presents a step to increase the native appearance on the Macintosh \(similar to [[25]](25.md).\) ![Comparison of Native (to left) and Standard Menu Buttons.](../assets/51compare.gif) # Reference Implementation The proposed change is now implemented as a loadable extension \(in C\) on Macintosh, and can be downloaded <http://hem.fyristorg.com/matben/download/MacMenuButton.sit> . This implementation differs from the other buttons in Mac Tk \(button, radiobutton, checkbutton\), which use a mixture of native Apple drawing code and Tk drawing code, since it uses only native Apple code for drawing. This extension requires Tcl/Tk 8.3.2p1 or later due to the changed stub loading mechanism. The new implementation is not a complete replacement since it lacks the _-bitmap_ and _-image_ options, and a few other things, see below. The changes necessary are: * Replace the _tkMacMenubutton.c_ file with the new one. * Add a MENU resource item, which is included in the shared library, but needs to be added to the core. * Modifications to _tkMacFont.c_ \(see appendix\). Put declaration so it can be used from any file. Possibly also add the new function to the stub table since it can be practical for other extension writers. * Need to check for the presence of the Appearance manager: if (TkMacHaveAppearance()) use native (new) menubutton else use present menubutton All functionality from the documentation that is applicable is implemented in the extension, with some exceptions: * The _-image_ and _-bitmap_ options are not supported, yet. * There is no button pressed \(SELECTED\) flag so it highlights when the mouse enters, just as a reminder that it must be fixed. \(see appendix\) * Don't know which color to pick for the three pixels in each corner. It is now the _-background_ color, but the ordinary button uses _-highlightbackground_? * The position of the popup menu should be changed in order to conform better with standard Mac appearance.. * Something needs to be done so that we can get Mac native font stuffs from a _Tk\_Font_ object; I've included a crude hack in the appendix. * It is compliant to the Appearance Manager which means that foreground and background colors are set via themes and not from command switches. * Minor differences to comply with the Appearance Manager. All these deviations are consistent with the look-and-feel of Mac OS 8.0 and on. Existing scripts using menubutton are compatible with the new menubutton. Open questions: * Option to use for the color of the corner pixels. * If \(and how\) a SELECTED flag should be added to _tkMenuButton.h_, and code to support it in _tkMenuButton.c_. * Implementation of the _-bitmap_ and _-image_ options. * A _-compound_ option as described in TIP \#11. # Copyright This document has been placed in the public domain. # Appendix * Addition to _tkMenuButton.h_: #define SELECTED 8 > Other modifications to tkMenuButton.c must be made to support this flag. * Addition to _tkMacFont.c_ \(possibly add to exported functions\): /* *--------------------------------------------------------------------------- * * GetMacFontAttributes -- * * Takes a Tk_Font and gets the Mac font attributes faceNum, size, and style. * Note that the Mac font size is in pixels while the Tk_Font size is * in points. No need to do any UTF-8 translations since this is * implicit in GetFamilyOrAliasNum(). * The code here is essentially a modified TkpGetFontFromAttributes() and * InitFont(), both from tkMacFont.c. * * Results: * Sets the Mac font attributes. * * Side effects: * None. * *--------------------------------------------------------------------------- */ void GetMacFontAttributes( Tk_Window tkwin, /* Tk window. (in) */ Tk_Font tkFont, /* Tk font. (in) */ short *faceNumPtr, /* Mac font face id. (out) */ short *macSizePtr, /* Mac font size in pixels. (out) */ Style *stylePtr) /* Mac font style specifier. (out) */ { int i, j; char *faceName, *fallback; char ***fallbacks; MacFont *fontPtr; const TkFontAttributes *faPtr; int size; /* Size in points. */ /* * This is just a macro to access the attribute struct member. */ faPtr = GetFontAttributes(tkFont); /* * Algorithm to get the closest font to the one requested. * * try fontname * try all aliases for fontname * foreach fallback for fontname * try the fallback * try all aliases for the fallback */ *faceNumPtr = 0; faceName = faPtr->family; if (faceName != NULL) { if (GetFamilyOrAliasNum(faceName, faceNumPtr) != 0) { goto found; } fallbacks = TkFontGetFallbacks(); for (i = 0; fallbacks[i] != NULL; i++) { for (j = 0; (fallback = fallbacks[i][j]) != NULL; j++) { if (strcasecmp(faceName, fallback) == 0) { for (j = 0; (fallback = fallbacks[i][j]) != NULL; j++) { if (GetFamilyOrAliasNum(fallback, faceNumPtr)) { goto found; } } } break; } } } found: *stylePtr = 0; if (faPtr->weight != TK_FW_NORMAL) { *stylePtr |= bold; } if (faPtr->slant != TK_FS_ROMAN) { *stylePtr |= italic; } if (faPtr->underline) { *stylePtr |= underline; } if (faPtr->size == 0) { size = -GetDefFontSize(); } else { size = faPtr->size; } *macSizePtr = (short) TkFontGetPixels(tkwin, size); } |
Name change from tip/52.tip to tip/52.md.
|
| < | < | | | | | | | | | | > | | | | | | | | | | < < > > | | | | | | | | | | | < > | | | | | < > | | | | | | | | | | | | | | < < > > | | | | | < < | > > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 52: Hierarchical Namespace Lookup of Commands and Variables Author: David Cuthbert <[email protected]> Author: Andreas Kupries <[email protected]> State: Withdrawn Type: Project Vote: Pending Created: 09-Aug-2001 Post-History: Discussions-To: news:comp.lang.tcl Keywords: namespace,lookup,hierarchy Tcl-Version: 8.5 ----- # Abstract This TIP proposes to change the command and variable namespace lookup system so that the full hierarchy of namespaces is parsed, rather than just the current namespace followed by the global namespace. This is primarily intended to rectify problems often encountered with the use of [incr Tcl] \(ITcl\) and namespaces. In addition, package encapsulation can be enhanced with judicious application of this feature. # Rationale Currently, the following code is invalid in Tcl/ITcl: package require Itcl namespace eval SampleNS { proc Hello {} { puts "Hello world!" } ::itcl::class X { public constructor {} {} { Hello } } } SampleNS::X x1 ;# Error: invalid command name "Hello" This is due to the fact that ITcl classes double as namespaces. Therefore, the lookup of _Hello_ takes place first in _::SampleNS::X_, followed by _::_ \(the global namespace\). The current workaround - to reopen the class' namespace and issue a _namespace import_ directive - is of limited value since _namespace import_ is not capable of bringing in names defined later on. The following code illustrates this point: package require Itcl namespace eval SampleNS { ::itcl::class X1 { public method GetSibling {} { return [X2 \#auto] } } namespace eval X1 { namespace import ::SampleNS } # Further down, or perhaps in a separate file source later: ::itcl::class X2 { } } set x [SampleNS::X1 \#auto] $x GetSibling ;# Error: invalid command name "X2" Non-ITcl code can also make use of hierarchical namespaces to better encapsulate support procedures. In this example, the child namespace _private_ illustrates that the _GetUniqueId_ procedure should not be used outside of the package; however, _GetUniqueId_ still has access to the procedures and variables in the package's main namespace: # MyPackage namespace eval MyPackage { variable nextId 0 namespace eval private { proc GetUniqueId {} { variable nextId return "MyPackage.[incr nextId]" } } proc CreateObject {} { set name ::[private::GetUniqueId] proc $name args { body } return $name } } # Specification Currently, the _NAME RESOLUTION_ section of the _namespace_ documentation states: > If the name does not start with a :: \(i.e., is _relative_\), Tcl follows a fixed rule for looking it up: Command and variable names are always resolved by looking first in the current namespace, and then in the global namespace. Namespace names, on the other hand, are always resolved by looking in only the current namespace. The proposed change to this is as follows: > If the name does not start with a :: \(i.e., is _relative_\), Tcl follows a fixed rule for looking it up: Command and variable names are always resolved by traversing the namespace hierarchy - that is, the current namespace is examined first, followed by the parent, the parent's parent, and so on, until \(finally\) the global namespace is examined. Namespace names, on the other hand, are always resolved by looking in only the current namespace. By keeping the current behaviour for namespace names, this TIP affects only completely unqualified commands and variables \(i.e. those that do not contain ::\). Changing the behaviour of partially qualified names \(those that are relative _and_ contain ::\) is often unintuitive and can lead to unexpected errors. # Consequences 1. ITcl classes and child namespaces can refer to command and variable names in their parent hierarchy without requiring the names to be fully qualified. This improves the intuitiveness and readability of Tcl code. In addition, it can reduce the brittleness of the code should parent namespace names undergo a change \(e.g., _namespace eval scriptics.com_ to _namespace eval ajubasolutions.com_\). 2. Currently well-defined behaviour is modified. This can break existing code if the following conditions are met: > \* The code employs the use of namespaces with a depth greater than one below the global namespace. > \* The code creates a variable or procedure in a parent namespace with the same name as a variable or procedure in the global namespace. > \* The code in the child namespace uses unscoped names to refer to commands and/or variables in the global namespace. > A cursory examination of existing Tcl code available on the Internet revealed no code which used deeply nested namespaces. 3. Existing well-defined behaviour of the internal Tcl function _TclGetNamespaceForQualName_ is modified. Under the sample implementation, the _altNsPtrPtr_ parameter \(which currently returns a pointer to the global namespace if a name was found there\) always returns NULL. It is up to the calling functions \(e.g., Tcl\_FindCommand and Tcl\_FindNamespaceVar\) to traverse the hierarchy. Although the Tcl and Tk code-base can be modified to accommodate this, extensions which depend on this internal function may be broken. # Namespace History Namespaces were originally developed by Michael McLennan for ITcl, and apparently had this hierarchical resolution feature. When they were adopted into Tcl, an optimisation was made which led to the current behaviour. This TIP argues for the reversal of this decision based on experiences with the new behaviour. # See Also * Tcl manual page _namespace_. * Tcl source code file _tcl8.4a3/generic/tclNamesp.c_. * Sample implementation at <http://www.kanga.org/tclnamespace/> # Comments * Andreas Kupries: > Related information: SF entry [ #218101 ] "no man page for library procedures Tcl\_AddInterpResolver Tcl" <http://sourceforge.net/tracker/?func=detail&aid=218101&group_id=10894&atid=110894> > Not addressed in this TIP: Impact on speed of the interpreter. \(Seeking out mail on Tcl core where author of talks about this\) # Notice of Withdrawal This TIP was Withdrawn by the TIP Editor following discussion on the tcl-core mailing list. The following is a summary of reasons for withdrawal: > Insufficiently subtle. 52 will break any code that assumes the current behaviour \(and you can bet someone will have that assumption\) and 142 doesn't let two namespaces have different search paths \(unless the variable is always interpreted locally, which just creates bizarre variable name magic.\) # Copyright Copyright © 2001 by David Cuthbert. Distribution in whole or part, with or without annotations, is unlimited. |
Name change from tip/53.tip to tip/53.md.
|
| < | < | | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 53: Addition of 'assert' Command Author: Gerald W. Lester <[email protected]> Author: Kevin Kenny <[email protected]> State: Withdrawn Type: Project Vote: Pending Created: 14-Aug-2001 Post-History: Keywords: bytecode,compiler Tcl-Version: 8.4 ----- # Abstract This TIP proposes the addition of an _assert_ command and supporting infrastructure to the Tcl core. # Rationale Many languages, including other scripting languages, have assertion checking features that can be used to assist in validating program correctness. Typically, these assertion checking features can be "compiled out" of production systems so as not to impact performance. To have a similar effect in Tcl, the assertion checking features must be implemented at the byte code compiler level. If, doing byte code compilation, an assert command is encountered the byte code stream generated will be dependent on the value of the _assert\_enabled_ command line option. If the option is true, a byte code stream will be emitted to implement the assert command. If the option is not true, no byte code will be emitted. Similarly, if the interpreter encounters an _assert_ command \(either compiled or uncompiled\), it will only execute it if the _assert\_enabled_ command line option is true. It is acceptable for the compiler to throw an error if the _booleanExpression_ is not brace quoted. # Tcl-Level Specification The manual entry for the _assert_ command is included here: ---- # NAME > assert - Assert a run time validation condition # SYNOPSIS assert booleanExpression messageText # DESCRIPTION > This command has no effect if the assert\_enabled command line option is not true at both compile and run time. If the _assert\_enabled_ command line option is true at both compile and run time, the following behavior will occur: > 1. The _booleanExpression_ will be evaluated > 2. If the _booleanExpression_ evaluates to a true value, _assert::failed_ will be called at the global level with _messageText_ as its one and only parameter. > The default implementation of _assert::failed_ will write _messageText_ to standard out and _exit_ with a status code of 1. ---- # Remarks This TIP has been withdrawn because of other changes, both inside and outside the Tcl core. 1. The bytecode compiler \(8.4a4\) contains code that recognizes a no-op procedure of the form _proc no-op args \{\}_ and generates no bytecode if such a procedure is called with arguments that have no side effects. 2. The _control_ package within tcllib implements a _::control::assert_ procedure that provides all the requested functionality. These two, taken together, provide an implementation of the requested functionality that is acceptable to the original author of this TIP. # Copyright This TIP is in the public domain. |
Name change from tip/54.tip to tip/54.md.
|
| < | < | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 54: Using PURLs to Unite the Tcl Webspace Author: Andreas Kupries <[email protected]> Author: Jeff Hobbs <[email protected]> State: Withdrawn Type: Process Vote: Pending Created: 16-Aug-2001 Post-History: ----- # Abstract This TIP proposes the use of PURLs to unify the scattered landscape of Tcl URLs into a coherent set of information about the language, the community, extensions, etc. # Background & Rationale One of the recurring themes in the community in general \(and news:comp.lang.tcl in particular\) is the lack of central website people can turn to for an introduction to the language, the community, search for extensions and packages, et cetera. Most of the solutions proposed so far have the distinctive disadvantage of not being able to use the existing sites and bind them into a whole. This is further aggravated by the fact that the 'natural' domain names, like for example <http://www.tcl.com/> and <http://www.tcl.org> are already taken by other entities, commercial and not, and thus not available anymore. We do have control of the <http://www.tcl-tk.net/> domain, provided by David Welton. Instead of giving up at this point I propose to use PURLs a.k.a. _Persistent URLs_ to construct a virtual website \(the _Tcl space_\) out of all the existing independent efforts. See <http://www.purl.org/> for more explanations of PURLs. Note that PURLs not only can refer to single URLs but to entire sites. The latter is done through a technique called 'partial redirection'. This ... is emphasized here because partially redirected PURL have to be used with a trailing slash whereas PURLs referring to single URL must not have a trailing slash. In the lists below partially redirected PURLs are indicated by a trailing slash. A restriction we face is that PURLs are case insensitive. This means that the names we will have to come up with have to be unique even with case removed. One of the most important features is the persistency. In real life however organizations, people, websites, etc. can disappear. According to <http://www.purl.org/OCLC/PURL/FAQ\#toc3.14> the PURL stays in existence but can be redirected to a page detailing the history of the purl. This would include the decommission. We could also do our own scheme and redirect the purl to a page explaining the history in a more Tcl-specific manner \(like: Company went out of business, was acquired, etc.\). # Specification This TIP is driven by several conflicting needs: * The names will be persistent, so give them some thought before creating them; they cannot be undone. This also implies that we to set up a simple and minimal structure first so as not to block future enhancements and flexibility. * Define the structure now before the URN space gets as scattered as the URL space is. Note that this process has already begun. The PURL resolver at <http://www.purl.org/> currently has registered 24 Tcl-related PURLs which are not bound together in the framework proposed here. Action is necessary to prevent further confusion. Of the existing PURLs the PURL domain _/tcl_ created by Don Libes is the most promising one for the unification of the Tcl space. Six of the 24 aforementioned PURLs are defined below this domain too, providing a \(good\) framework on which to build. The existing PURLs and sub-domains in the _/tcl_ domain are: * _expect_ - reference to the homepage of the expect extension * _faq_ - reference to the main FAQ * _faqs_ - introduction to the available FAQ documents. * _home/_ - refers to the Tcl Developers Xchange * _tip/_ - refers to the TIP archives * _wiki_ - refers to the entry page of the Tcl'ers WIKI With the exception of _expect_ all of these are general classes and/or refer to important sites. They are used as is, except for _expect_ which has to be redirected into the proposed sub-domain _package_. The following new sub-domains covering the most important general classes of information and/or websites are proposed here. Please note that the examples used in the list below are using purely informal everyday names to refer to entities in the proposed domain. These examples should not be seen as suggestions for the concrete naming scheme used by the domain. * _announce_ - Direct reference to a page explaining how to announce packages, applications and other tcl-related news and linking to the relevant newsgroups, mail archives and submission addresses. This includes, but is not restricted to: > \* A link to the newsgroup _comp.lang.tcl.announce_. > \* A link to the eGroups/Yahoo archive of the c.l.t.a newsgroup. > \* The submission address of c.l.t.a. to directly submit via email announcements. * _newsletter_ - Direct reference to an archive of _Tcl-URL!_. * _package/_ - Sub-domain to contain references to the homepages of the known packages. This TIP makes no distinction between C-level extensions and script libraries. From the point of view of the core these are all packages to be required. > Examples of packages are _Expect_, _tcllib_, etc. * _application/_ - Sub-domain to contain references to the homepages of applications related to Tcl, written in Tcl or using it internally. > Examples of applications are _frink_, _tclHttpd_, _AOLServer_, etc. * _person/_ - Sub-domain to contain references to the homepages of people active in the community, as far as they are interested in such a reference. References in this domain shall be personal and not organization-related. The latter will go into their own domain. > Examples of people are _Larry Virden_, _Cameron Laird_, etc. * _org/_ - Sub-domain to contain references to organizations important to the Tcl community. > Examples are the Tcl Core Team, the Tcl Core Maintainers, Tcl-based based companies \(PhaseIt, ActiveState\), companies and organizations using Tcl \(NIST, CAS\), etc. # Management The _/tcl_ domain was created by Don Libes which made him automatically the maintainer of the domain <http://www.purl.org/maint/search_user.pl.cgi?userid=^LIBES$> . He has already extended the maintainership to the entity TCLGROUP <http://www.purl.org/maint/search_group.pl.cgi?groupid=^TCLGROUP$> , currently consisting of * Gordon Johnstone <[email protected]> * Jeffrey Hobbs <[email protected]> * Don Libes <[email protected]> * Andreas Kupries <andreas\[email protected]> * Larry Virden <[email protected]> * Don G. Porter <[email protected]> * Jean-Claude Wippler <[email protected]> For the future I propose that * High-level changes to the Tcl space, like new sub-domains, have to go through the TCT and the TIP process for approval. This is also in line with [[0]](0.md) declaring the responsibility of the TCT for the Tcl webspace. * The day-to-day routine of adding new packages, persons, organizations, etc. is delegated to a new group, the _Tcl Namespace Maintainers_. > Initially this group would consist of the people mentioned above, with membership open to volunteers from the community. # Discussion * All of the newly proposed sub-domains will be simple listings mapping from the names of the entities contained in them to the proper locations. Further categorization of the entities by topic, gender or other attributes is out of the scope of this TIP. This type of categorization rather is in the domain of general and specialized catalogs which can be set up later and then bound into the unified webspace proposed here. > Note that such catalogs can and should make use of the proposed domains to reduce the effort necessary by them to stay current with respect to the location of the referenced entities \(people, packages, etc\). * The first pre-draft of this TIP contained definitions for the names to use in the various domains. These definitions have been removed on the grounds that their format and other issues like resolution of naming conflicts, order of precedence, etc. are best handled in one or more separate documents. The role of this TIP is to lay down a framework within which the community can operate and not to fill in every conceivable detail. > These details can be discussed and decided upon by the group of maintainers proposed in the last section. * This proposal makes the Tcl community dependent on an external entity, namely the maintainers of <http://www.purl.org/.> This is considered acceptable. # Example The following examples show how to use PURLs, using some of the already existing ones: * <http://www.purl.org/tcl/tip/> refers to the TIP archive. * <http://www.purl.org/tcl/wiki/> refers to the Tcl'ers Wiki. # Copyright This document is in the public domain. |
Name change from tip/55.tip to tip/55.md.
|
| < | < | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 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 | # TIP 55: Package Format for Tcl Extensions Author: Steve Cassidy <[email protected]> Author: Larry W. Virden <[email protected]> State: Draft Type: Informative Vote: No voting Created: 16-Aug-2001 Post-History: ----- # Abstract This document specifies the contents of a binary distribution of a Tcl package, especially directory structure and required files, suitable for automated installation into an existing Tcl installation. # Rationale There is currently no standard way of distributing or installing a Tcl extension package. The TEA document defines a standard interface to _building_ packages and includes an _install_ target but presumes that the packages is being installed on the same machine as it was built. This TIP defines a directory structure and assorted files for the binary distribution of a package which can be placed into an archive \(for example zip or tar file\) and transferred for installation on another machine. A basic mechanism for installation of packages is also described. # Definitions The following definitions are excerpted from [[78]](78.md): package: A collection of files providing additional functionality to a user of a Tcl interpreter when loaded into said interpreter. > Some files in a package implement the provided functionality whereas other files contain metadata required by the package management of Tcl to be able to use the package. distribution: An encapsulation of one or more _packages_ for transport between places, machines, organizations, and people. shared library: A piece of binary code that provides a set of operations and data structures like a normal library, but which does not need to be physically incorporated into the executables that use it until they are actually executed. This is the normal way to distribute binary code for a Tcl package such that it can be incorporated into a Tcl interpreter with the _load_ command. On Windows, shared libraries are known as DLLs, on the Macintosh ... # References Much of the required structure for an installable distribution is defined by the requirements of Tcl's existing package loading methods. The structure of an installable distribution should largely mirror the structure of an installed package where possible. The R system \(a statistical package <http://www.r-project.org/> \) has a well defined package format which enables automatic installation of new packages and integration of documentation and demonstration programs for these with that of the main R system. A number of packaging and installation systems \(for example, Debian <http://www.debian.org> and RPM <http://www.redhat.com> \) have been developed by the Linux community which provide an interesting range of facilities. These systems commonly provide facilities for pre and post installation scripts and pre and post removal scripts to help set up and shut down packages. Also included are detailed dependency relations between packages which can be used by an installer to ensure that a package will work once it is installed or warn of potential conflicts after installation. A significant part of this proposal is the proposed format of the package metadata which derives from other metadata standardisation efforts, mainly the Dublin Core <http://purl.org/dc/> and the Resource Description Framework <http://www.w3.org/RDF> . # Requirements The simplest case of a Tcl package is one that contains only Tcl code; these will be considered first, and the additional issues raised by packages containing compiled code will be dealt with later. The minimum contents of a Tcl only package are defined by the requirements of [package require xyzzy]. The package needs to be placed in a directory on the _auto\_path_ and must contain one or more _.tcl_ files which implement the functionality provided by the package. In addition to these files, it is useful to include documentation for the commands implemented by the package and some additional metadata about the author etc. Distributions might also optionally include demonstration scripts and applications illustrating their use, these could either be incorporated into the documentation or included as stand-alone Tcl files. Distributions which include shared libraries add an additional layer of complexity since these will only run on the platforms for which they have been compiled. There are two clear options here: either distributions are platform specific, intended for installation on one platform alone, or the structure of the distribution is extended to allow the option of including multiple shared libraries. The latter option would allow a single installation to serve multiple platforms and so should be preferred although this TIP will not _require_ a distribution to support multiple platforms. # Proposed Directory Structure The following directory structure is proposed for an installable distribution: packagename$version + DESCRIPTION.txt -- Metadata, description of the package + doc/ -- documentation + examples/ -- example scripts and applications + $architecture/ -- shared library directories + pkgIndex.tcl -- package index file (optional) In addition, a distribution may include any additional files or directories required for its operation. _DESCRIPTION_ is a file containing metadata about the package\(s\) contained in the distribution. Its format will be described in a later section of this document. The file _pkgIndex.tcl_ currently required by the package-loading mechanism of the Tcl core is _optionally_ distributed. In most cases, it will be generated by the installer; all the information which is necessary to do this is part of the distribution. Distribution authors should only include _pkgIndex.tcl_ if special features of their distribution mean that the generated file would not work. If the _pkgIndex.tcl_ file is included in the distribution it should load files from their locations within the distribution directory structure. For example, Tcl files should be loaded from the _tcl_ directory. _doc/_ directory contains documentation in an accepted format. Currently Tcl documentation is delivered either in source form \(nroff or TMML\) or as HTML files. Given the lack of a standard cross platform solution, this TIP does not require a specific format; however, the inclusion of either a text or HTML formatted help file is strongly encouraged. If HTML formatted help is included the main file should be named _index.html_ or _index.htm_ so that it can be linked to a central web page. If only plain text documentation is included there should be a file called _readme.txt_ \(in either upper or lower case\) which will serve as the top level documentation file. _examples/_ directory contains one or more Tcl files giving examples of the use of this package. These should be complete scripts suitable for either sourcing in tclsh/wish or running from the command line. The examples should be self contained and any external data should be included in files in this directory or a sub-directory. This directory should contain a file _readme.txt_ which explains how to run the examples and provides a commentary on what they do. _$architecture_ directories contain shared libraries for various platforms. The special architecture _tcl_ is used for Tcl script files. They either implement the package or contain companion procedure definitions to the shared libraries of the package. The distribution need not provide all possible combinations of architectures and may only provide one shared library. This structure is proposed to allow shared libraries to co-exist in a multi-platform environment and to allow binary packages to be distributed in multi-platform distributions. The architectures included in the distribution should be named in the DESCRIPTION.txt file. The possible values of $architecture and methods for generating them are discussed in a later section. # Metadata This section defines the metadata describing the package contained in the distribution in a format-neutral way. The model for this data is that provided by the Resource Description Framework \(RDF <http://www.w3.org/rdf> \) which defines a triple based data model. The RDF model defines objects, their properties and relationships between them. In addition, where possible, element names are taken from the Dublin Core Metadata Element Set <http://dublincore.org/documents/1999/07/02/dces/> which defines a standard set of element names for metadata. Dublin Core names are marked with DC in parentheses in the following list. In a package description, the object being described is the package itself, hence the element names are all intended to describe packages. Other objects might be described including people and organisations. The package description should not include these objects but a package repository might store them separately keyed on the values stored in this description \(e.g. email addresses of creators\). * _Identifier_ \(DC\) > This element is a string containing the name of the distributed package. The name may consist only of alphanumeric characters, colons, dashes and underscores. This name should correspond to the name of the package defined by this distribution \(that is, the code should contain _package provide xyzzy_ where _xyzzy_ is the value of this element. > Care must be taken to make this name unique among the package names in the archive. To overcome this, namespace style names separated by double colons should be used. > Examples: xyzzy, tcllib, xml::soap, cassidy::wonderful-package\_2 * _Version_ > This element is a string containing the version of the package. It consists of 4 components separated by full stops. The components are _major version_, _minor version_, _maturity_ and _level_; and are written in this order. > The major and minor version components are integer numbers greater than or equal to zero. > The component _maturity_ is restricted to the values a, b. The represent the maturity states _alpha_, _beta_ respectively. For a production release, this component can be omitted. > The _level_ component allows a more fine-grained differentiation of maturity levels. When a package has maturity _production_ the _level_ component is often called the _patchlevel_ of the package. If the _level_ component is zero, it may be omitted. > The period each side of the _maturity_ component may be omitted. > Valid version numbers can be decoded via the following regular expression: regexp {([0-9]+)\.([0-9]+)\.?([ab])?\.?([0-9]*)} $ver => major minor maturity level > Examples: 8.4.0 8.4a1 2.5.b.5 * _Title_ \(DC\) > This element is a free form string containing a one sentence description of the package contained in the distribution. > Example: Installer Tools for Tcl Packages * _Creator_ \(DC\) > This element is a string containing the name of the person, organisation or service responsible for the creation of the package optionally followed by the email address of the author in angle brackets <http://www.faqs.org/rfcs/rfc2822.html> . More detail about an author can be provided in a separate object in the RDF description and if this is provided the email address should be used as the value of the Name field in that object. > If there is more than one author this field may appear multiple times. > Email addresses may be obfuscated to avoid spam harvesters. > Example: Steve Cassidy <Steve.Cassidy at mq dot edu dot au> * _Contributor_ \(DC\) > This element is a string analogous to the Creator element which contains the name of a contributor to the package. * _Rights_ \(DC\) > Typically, a Rights element will contain a rights management statement for the resource, or reference a service providing such information. This will usually be a reference to the license under which the package is distributed. This can be a free form string naming the license or a URL referring to a document containing the text of the license. > If the Rights element is absent, no assumptions can be made about the status of these and other rights with respect to the resource. > Examples: BSD, <http://www.opensource.org/licenses/artistic-license.html> * _URL_ > This element is a string containing an url referring to a document or site at which the information about the package can be found. This url is _not_ the location of the distribution, as this might be part of a larger repository separate from the package site. > Example: <http://www.shlrc.mq.edu.au/~steve/tcl/> * _Available_ \(DC\) > This element is the release data of the package in the form YYYY-MM-DD. > YYYY is a four-digit integer number greater than zero denoting the year the distribution was released. > MM is a two-digit integer number greater than zero and less than 13. It is padded with zero at the front if it less than 10. It denotes the month the distribution was released. The number 1 represents January, 2 represents February; and 12 represents December. > DD is a two-digit integer number greater than zero and less than 32. It is and padded with zero at the front if less than 10. It denotes the day in the month the distribution was released. > A valid data string can be obtained with the Tcl command [clock format [clock seconds] -format "%Y-%m-%d"] > Example: 2002-01-23 > \(The DC element is Date but it can be refined to Created, Available, Applies\) * _Description_ \(DC\) > This element is a free form string briefly describing the package. * _Architecture_ > This element is a string describing one of the architectures included in the distribution. As a distribution is allowed to contain the files for several architectures, this element may appear multiple times and should correspond to a directory in the distribution. * _Require_ > Names a package that must be installed for this package to operate properly. This should have the same format as the _package require_ command, eg. _?-exact? package ?version?_. > Example: http 2.0 * _Recommend_ > Declares a strong, but not absolute dependency on another package. In most cases this package should be installed unless the user has specific reasons not to install them. * _Suggest_ > Declares a package which would enhance the functionality of this package but which is not a requirement for the basic functionality of the package. * _Conflict_ > Names a package with which can't be installed alongside this package. The syntax is the same as for Require. If a conflicting package is present on the system, an installer might offer an option of removing it or not installing this package. * _Subject_ \(DC\) > The topic or content of the package expressed as a set of Keywords. At some future time, a set of canonical keywords may be established by a repository manager. The following Dublin Core elements were not included in the standard set above but may be used in a package description if appropriate. * _Publisher_ > An entity responsible for making the package available. * _Type_ > The nature or genre of the content of the resource. For a Tcl package the value of this element would be Software if the DCMI Type Vocabulary <http://au.dublincore.org/documents/2000/07/11/dcmi-type-vocabulary/> was used. A more useful set of types might be developed in the future for Tcl packages. * _Format_ > The physical or digital manifestation of the resource. This might be used by archive maintainers to specify the format of a package archive, eg. zip, tar etc. * _Source_ > A Reference to a resource from which the present resource is derived. * _Language_ > A language of the intellectual content of the resource. Could be used if multi-language packages are available. Should use the two letter language code defined by RFC 1766, eg. 'fr' for French, 'en' for English. # Encoding of the Metadata The primary means of storing RDF data is using XML but it can be stored in many other formats. This TIP prescribes a simple text based encoding according to the RFC 2822 format which is described in this section. Data stored in this format can be converted to XML format for use by other tools, similarly XML formatted descriptions can be converted into this text format without loss of information. The text format description is stored in the file _DESCRIPTION.txt_. The XML formatted version of the data may be stored in the file _DESCRIPTION.rdf_ within the archive and may be automatically generated if not present. The general format of this file is that of a RFC 2822 mail message, without body and using custom headers. The available headers are the case-independent logical names from the preceding section but may be augmented by other fields defined by repository maintainers or other applications. The headers are allowed appear in any order. Example: Identifier: stemmer Version: 1.0.0 Title: A stemmer for English. Creator: Steve Cassidy <[email protected]> Description: Provides a procedure to remove any prefixes or suffixes on a word to give the word stem. Uses Porter's algorithm to do this in an intelligent manner with an accuracy of around 80%. Rights: BSD URL: http://www.shlrc.mq.edu.au/emu/tcl/ Available: 2001-08-16 Architecture: tcl Subject: linguistics Subject: text # Combination Distributions It is often useful to combine a number of related packages so that they can be installed together to provide a certain kind of functionality, for example, web page production tools or database access. Perl uses the term _Bundle_ to refer to such a group of related packages. There are two alternative mechanisms for distribution of such a package within the mechanisms suggested here. Firstly, since a distribution may contain more than one package, the set of files making up the various packages could be combined together and described by a single DESCRIPTION.txt file. This is similar to the way that tcllib is currently distributed. The disadvantage would be that all of the Tcl files implementing these packages would have to reside in the same directory which could cause name clashes. The second alternative is to create a distribution consisting of only a DESCRIPTION.txt file to describe which Requires the component packages causing them to be installed from the repository. For example, tcllib might be described as follows: Identifier: tcllib Version: 1.0.0 Title: The Standard Tcl Library Description: This package is intended to be a collection of Tcl packages that provide utility functions useful to a large collection of Tcl programmers. Rights: BSD URL: http://sourceforge.net/projects/tcllib Contributor: Andreas Kupries <andreas_kupries at users dot sourceforge dot net> Contributor: Don Porter <dgp at users dot sourceforge dot net> Require: base64 Require: cmdline Require: csv ... Installing tcllib would cause the installer to fetch base64, cmdline, csv etc from the repository and install them in order to satisfy the tcllib requirement. A new pkgIndex.tcl file could be constructed to load all of these packages if _[package require tcllib]_ was called. # Architecture Possible values for $architecture in the directory structure include: * the value of _tcl\_platform\(platform\)_: windows, unix, macintosh * a composite of tcl\_platform values: _$tcl\_platform\(machine\)-$tcl\_platform\(os\)-$tcl\_platform\(osVersion\)_ * a canonical system name as returned by _config.guess_: _i686-pc-linux-gnu_ # Installing Packages A package structured according to this TIP can be installed using the following steps: 1. Download the package archive \(eg. zip file\) 2. Locate a writable directory included on $auto\_path \(or ask for a installation directory\) 3. Unpack the archive in the desired location. 4. Run pkg\_mkIndex with appropriate arguments to generate a pkgIndex.tcl file if none is present. Arguments will include the appropriate Architecture directories for the platform. 5. _\(optional\)_ link help files and demos to the central index. # Alternatives Alternatives might be considered for the package DESCRIPTION.txt file, for the documentation directory and for the location of shared libraries. An alternative for package description file is to include an alternative package description, for example the XML based \`\`ppd_ format used to describe Perl packages on the ActiveState Perl package repository. The main motivation for the simple format proposed is that it is trivial for authors to write and trivial for programs to read and can be transformed into standards based RDF XML. The use of the DC element names means that search engines etc. will be able to usefully index the packages in a repository. |
︙ | ︙ | |||
528 529 530 531 532 533 534 | The alternative to having shared libraries in specific directories is to have separate packages for each new platform. This has the advantage of making the packages smaller and more closely correspond to the existing directory structure of an installed package. The main motivation for the suggested directory structure is to allow multi-platform packages or to facilitate multi-platform installations. | | | | | > | 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 | The alternative to having shared libraries in specific directories is to have separate packages for each new platform. This has the advantage of making the packages smaller and more closely correspond to the existing directory structure of an installed package. The main motivation for the suggested directory structure is to allow multi-platform packages or to facilitate multi-platform installations. # Supporting Tools The standards outlined in this TIP should be supported by Tcl scripts to: * Generate empty package templates for new projects. * Validate package directories or archive files. * Read and write the DESCRIPTION.txt file and provide a standard interface to the information it contains. Convert between RFC 2822 and XML formats. * Install a package from an appropriately structured archive. In addition, the TEA standard should be extended with a _package_ makefile target which will act like the current _install_ target but which will copy files to a local directory and optionally build an archive of the package for distribution. # Copyright This document has been placed in the public domain. |
Name change from tip/56.tip to tip/56.md.
|
| < | | | | | | < | | > | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 56: Standardize Call Interface to Tcl_Eval* Functions State: Final Type: Project Tcl-Version: 8.4 Vote: Done Post-History: Author: Miguel Sofer <[email protected]> Created: 28-Aug-2001 ----- # Abstract This TIP replaces _Tcl\_EvalTokens_ with _Tcl\_EvalTokensStandard_, which obeys the standard result management conventions for script evaluation functions. # Rationale The standard call interface for _Tcl\_Eval\*_ functions returns a Tcl completion code \(TCL\_OK, TCL\_ERROR, TCL\_RETURN, TCL\_BREAK, or TCL\_CONTINUE\), and sets a result object in the interpreter. The single exception is the function _Tcl\_EvalTokens_, that returns a pointer to the result object, or a NULL when an exception occurs. This effectively transforms all exceptions into errors. This TIP proposes to replace _Tcl\_EvalTokens_ with a new function _Tcl\_EvalTokensStandard_ that performs the same chores but adheres to the standard call interface. There are two arguments for the replacement of _Tcl\_EvalTokens_: * Present a consistent call interface to all _Tcl\_Eval\*_ functions. * Allow the return of non-error exceptional returns when evaluating tokens; the impossibility to do this is the cause of Bugs \#455151 \(<https://sourceforge.net/tracker/index.php?func=detail&aid=455151&group\_id=10894&atid=110894\)> and \#219384 \(<https://sourceforge.net/tracker/index.php?func=detail&aid=219384&group\_id=10894&atid=110894\)> # Proposed Change The proposal is to deprecate the use of _Tcl\_EvalTokens_ and replace it with a new _Tcl\_EvalTokensStandard_. The core should only use the new function, the old one remains only for backward compatibility with extensions. The proposal is implemented in the patch included in [Bug: 455151] <https://sourceforge.net/tracker/index.php?func=detail&aid=455151&group\_id=10894&atid=110894> # Copyright This document has been placed in the public domain. |
Name change from tip/57.tip to tip/57.md.
|
| < | < | | | | | | | | | > | | | | | | | | | | | | | | | | | > | 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 | # TIP 57: Move TclX's [lassign] into the Tcl Core Author: Donal K. Fellows <[email protected]> Author: Agnar Renolen <[email protected]> Author: Don Porter <[email protected]> State: Final Type: Project Vote: Done Created: 30-Aug-2001 Post-History: Tcl-Version: 8.5 ----- # Abstract This TIP proposes to move the _lassign_ command from the TclX extension into the Tcl core to make multiple assignment a much easier process for people. # Rationale In many cases, a command needs to return more than one return value to the caller. For example, suppose that the statement: set coords [LocateFeature $featureID] would set the variable "coords" to a list containing two elements "x" and "y". Assume that you need to set the "x" and "y" components directly, you can do this today using the following statement: foreach {x y} [LocateFeature $featureID] {} Now, this is not what the _foreach_ command was designed for, and it is not obvious at first glance from the source code what the statement does. Although it is quite useful for the purpose described in this TIP, It would be more logical if the developer could write the following: set {x y} [LocateFeature $featureID] or mset {x y} [LocateFeature $featureID] However, there is already a command in TclX for doing this kind of operation: [lassign]. Given that many people already know TclX, importing the command from there makes a great deal of sense. It also has the nice feature of returning those list items that were not assigned, making it easy to strip a few words off the front of a list. That sort of operation is useful when performing tasks like command-line option parsing. # Proposal Define a new command in Tcl called [lassign] with the following syntax \(_$val_ indicates an argument that the caller would supply\): lassign $listValue $varName ?$varName ...? The command interprets its first argument as a list value and all subsequent arguments as variable names. The first item in the list value \(i.e. at index 0\) will be assigned to the first variable named, the second item in the list value will be assigned to the second variable named \(if present\), etc. When there are more variables than list items, the remaining variables will be assigned the empty string. The result of the command is a sublist of the input list-value that contains only items that were not assigned to a variable; if all values were assigned, the result is an empty list. This is exactly the specification of the behaviour of the correspondingly-named command in TclX. # Notes It should be possible to efficiently compile [lassign] in many cases, which would make a tremendous difference in execution speed over not only the TclX version of [lassign], but also over the [foreach] "idiom", especially when assigning to variables that are not simple local variables \(the case which [foreach] compilation is optimized for.\) For this reason, I'm not committing to implementing [lassign] using the TclX code. This TIP was substantially different in the past. Please view the CVS history for details. # Copyright This document is placed in the public domain. |
Name change from tip/58.tip to tip/58.md.
|
| < | < | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 58: Extend [set] to Assign Multiple Values to Multiple Variables Author: Anselm Lingnau <[email protected]> State: Rejected Type: Project Vote: Done Created: 02-Sep-2001 Post-History: Tcl-Version: 8.5 ----- # Abstract This TIP proposes a multiple assignment command as a backwards-compatible extension to the Tcl _set_ command. # Introduction Often one needs to assign values to several variables in close proximity. Right now several _set_ commands are necessary: set a 123 set b 456 or set a 123; set b 456 Or one abuses the _foreach_ command: foreach {a b} {123 456} break However, by analogy to the _variable_ and _array set_ commands, the following would be useful: set a 123 b 456 This would assign 123 to the variable _a_ and 456 to the variable _b_. Note that this extension is backwards-compatible to existing uses of the _set_ command since until now only one or two arguments to _set_ were allowed. # Specification The _set_ command is extended to allow either one or an even number of arguments. The behaviour in the case of one argument remains the one documented in the _set_ manual page; when an even number of arguments is specified, the behaviour of _set v0 e0 ... vn en_ is identical to that of the sequence of commands _set v0 e0; ...; set vn en_ according to the traditional semantics, except that the way Tcl processes commands means that _e0_ ... _en_ are all evaluated before any assignments are performed. I.e., the commands set a 1 set a 2 b $a puts $b print _1_, not _2_. If this is an issue you must use separate _set_ statements. The command _set v0 e0 ... vn en_ returns the value of _en_. # Rationale This extension is an obvious analogy to the _variable_ and _array set_ commands of Tcl, both of which allow an alternating list of names and expressions to be given as arguments. It is completely backwards-compatible \(_set_ invocations with more than two arguments used to be syntax errors\) and very easily implemented. This extension in no way prejudices against the adoption and use of other multiple-assignment commands, such as _lassign_ \(see [[57]](57.md)\). In particular, the _set_ extension is unsuitable for assigning a list result to a number of variables element by element. However, its simplicity and consistency to other similar Tcl commands is appealing. # Reference Implementation A patch to Tcl 8.4a3 which implements the _set_ extension may be found at <http://anselm.our-isp.org/set-patch.diff> - a patched Tcl 8.4a3 passes the Tcl 8.4a3 regression test suite with no test failures. No test cases nor documentation for the _set_ extensions have been devised yet but this is easy to do once there is a consensus that this feature is actually desirable. # Copyright This document is placed in the public domain. |
Name change from tip/59.tip to tip/59.md.
|
| < | < | | | | | | | > | | | | | | | | | | | | | | | | | < | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 | # TIP 59: Embed Build Information in Tcl Binary Library Author: Andreas Kupries <[email protected]> State: Final Type: Project Vote: Done Created: 04-Sep-2001 Post-History: Tcl-Version: 8.5 ----- # Abstract This TIP provides an interface through which Tcl may be queried for information on its own configuration, in order to extract the information directly instead of reading it from a Bourne shell file. An important reason to do this is to have the information not only available but also tightly bound to the binary configured by it, so that the information doesn't get lost. # Foreword This TIP proposes a rather small change to Tcl and tries very hard to follow the KISS principle. Given that the casual observer might find it rather long, be assured, the actual specification in here is not very long, nor complicated. Most of the following explanations were added to preserve the KISS principle and head off attempts to extend the TIP beyond its small goal and scope. Note: All instances of "Tcl library" in the following text refer to the generated installable library and not the script library coming with the core. # Background and Rationale The main reason for writing this TIP are the disadvantages inherent in the current way of storing the configuration of Tcl, namely in the file _tclConfig.sh_. * It is a separate file, easily lost or not installed at all, making it difficult for extension developers to access this information. > Note: The non-installation of development files like _tclConfig.sh_ might even be required by through vendor policies and such and thus not under the control of the package author or builder. * The name does not convey that _tclConfig.sh_ contains platform and build specific information. When installing different builds this usually leads to clashes. This makes it again difficult for extension developers to find the right file for their current build. * Not every extension generates such a file for use by other extensions. Thus, this TIP proposes: * an extension of the public API so that extensions are able to define configuration introspection commands and to declare the returned information during initialization with the information embedded into their installable libraries during compilation. * to embed the information about the configuration of the Tcl library as strings into the generated installable library and make them accessible at the script level through Tcl variables, thus allowing developers on any platform Tcl compiles on to access this information. The file _tclConfig.sh_ is _not_ replaced by this system, both sets of information exist in parallel. Neither is the variable _tcl\_platform_ replaced. This means that some information, like _threaded_, is held redundantly. Other information in _tcl\_platform_, like _user_ is runtime and not configuration information. The operating system information is important to a build system, but this is out of the scope of this TIP. # Interface Specification Any embedded information is made accessible at the Tcl level through a new command. The name of the command used by Tcl itself is _::tcl::pkgconfig_. Extensions have to use their own commands. These commands will be named _pkgconfig_ too and have to be placed within in the namespaces owned by the extensions initializing them. At the C-level the public API of the Tcl core is extended with a single function to register the embedded configuration information. This function is added to the public stub table of the Tcl core so that it can be used by Tcl and extensions to register their own configuration information in the system during initialization. The function takes three \(3\) arguments; first, the name of the package registering its configuration information, second, a pointer to an array of structures, and third a string declaring the encoding used by the configuration values. Each element of the array refers to two strings containing the key and the value associated with that key. The end of the array is signaled by an empty key. Formalized, name and signature of this new function are Tcl_RegisterConfig (CONST char* pkgName, Config* configuration, CONST char* valEncoding) typedef struct Config { char* key; char* value; } The string _valEncoding_ contains the name of an encoding known to Tcl. All these names are use only characters in the ASCII subset of UTF-8 and are thus implicity in the UTF-8 encoding. It is expected that keys are legible english text and therefore using the ASCII subset of UTF-8. In other words, they are expected to be in UTF-8 too. The values associated with the keys can be any string however. For these the contents of _valEncoding_ define which encoding was used to represent the characters of the strings. During compile time the value of _valEncoding_ is specified as a makefile variable for non-_configure_ based build systems and through the new option _--with-encoding=FOO_ of configure otherwise. The default value is _iso8859-1_. This approach gives us all what we desire with not too many drawbacks. * The default case \(no special characters\) requires no action on part of the builder at all. * The non-default case \(path containing special characters like Kanji\) is supported. * Cross-compilation is unimpeded and no more complex than normal compilation. * The requirement for conversion of strings is a drawback, but should not have a big impact on performance. It has no impact on the performance of scripts which do not use the embedded information. The impact is even more negligigble if the result of the conversion is cached. The function will * create a namespace having the provided _pkgName_, if not yet existing. * create the command _pkgconfig_ in that namespace and link it to the provided information so that the keys from _configuration_ and their associated values can be retrieved through calls to _pkgconfig_. The command _pkgconfig_ will provide two subcommands, _list_ and _get_. The first subcommand, _list_ takes no arguments and returns a list containing the names of the defined keys. The second subcommand takes one argument, the name of a key and returns the string associated with that key. # How to Gather the Embedded Information The information to be embedded is gathered in a platform-specific way and written into the file _generic/tclPkgConfig.c_. The different platforms may employ platform specific intermediate files to hold the information, but in the compilation phase only _tclPkgConfig.c_ will be used. * Under unix it is determined primarily by the existing _configure_ script. The configuration information coming from the Makefile, or from other compile time means, is embedded into the _tclConfig.c_ file by means of preprocessor statements \(\#ifdef ... \#endif\). * For the Windows and Mac platforms volunteers may have to create files _tclWinConfig.c.some-ext_ containing this information for each supported build environment, like VC\+\+, Borland, Cygwin, etc. > _tclWinConfig.c.vc_ = VC\+\+. > _tclWinConfig.c.bc_ = Borland. > _tclWinConfig.c.in_ = Cygwin. _.in_ is used because Cygwin can use configure to determine the values and embed them into a template. * As for other platforms, these are handled either like Unix or like Mac, depending on the availability and usability of _configure_. > Volunteers are required to write the appropriate files for their build environment. # Specification of Tcl Configuration Information The configuration information registered by Tcl itself is specified here. A discussion of the choices made here follows in the next section. Please read this discussion before commenting on the specification. The values associated with the keys below are all of one of the following types: * Boolean flag. Allowed values are all the values which are accepted by Tcl itself. Examples are: true, false, on, off, 1, 0 * String. General container for all other information. * Templated string. With respect to placeholders in the same format as 'Script' below, but does not have to be a valid Tcl script. * Script. A string containing a full Tcl script. The user should handle this string like a procedure body. The script is allowed to contain placeholders to be filled by the user of the string. Placeholders follow the syntax of full-braced Tcl variables, i.e. _$\{some\_name\}'. The actual values can be filled in by the user of the configuration information. Possible ways to do so are [regsub], [string map] or [subst -nocommand]. The best way however would be to use the script as a procedure body, with the placeholders as the arguments of the procedure. This will avoid many problems regarding bracing and the protection of special characters. > Which placeholders are possible for a particular script or template is described together with the meaning of the key. > Beyond the placeholders a script or templated string is allowed to contain references to other keys returned by the _config_ command. These references use the same variable syntax as the placeholders. The registered keys follow below. They will be always present with some value. Non-boolean keys not applicable to a particular platform will contain the empty string as their value. * Configuration of Tcl itself: > \* _debug_. Boolean flag. Set to false if Tcl was not compiled to contain debugging information. > \* _threaded_. Boolean flag. Set to false if Tcl was not compiled as thread-enabled. > \* _profiled_. Boolean flag. Set to false if Tcl was not compiled to contain profiling statements. > \* _64bit_. Boolean flag. Set to false if Tcl was not compiled in 64bit mode. > \* _optimized_. Boolean flag. Set to false if Tcl was compiled without compiler optimizations. > \* _mem\_debug_. Boolean flag. Set to false if Tcl has no memory debugging compiled into it. > \* _compile\_debug_. Boolean flag. Set to false if Tcl has no bytecode compiler debugging compiled in. > \* _compile\_stats_. Boolean flag. Set to false if Tcl has no bytecode compiler statistics compiled in. * Installation configuration of Tcl. In other words, various important locations. > \* _prefix,runtime_. String. The directory for platform independent files as seen by the interpreter during runtime. > \* _exec\_prefix,runtime_ String. The directory for platform dependent files as seen by the interpreter during runtime. > \* _prefix,install_. String. The directory for platform independent files as seen by the installer at install-time. > \* _exec\_prefix,install_. String. The directory for platform dependent files as seen by the installer at install-time. # Discussion The placement of this information into a separate package was proposed but rejected because of the trouble of finding the right information for the right library in the case of multiple configurations installed into the same directory space. Embedding into the library does not cost much space and binds the information tightly to the right spot. Another reason to do it this way is that this enables us to embed information coming from the Makefile itself \(like _MEM\_DEBUG_\) or from other compile time means. This would not be possible for a file generated solely by the Tcl configure. It would also restrict the embedding to the platforms which allow the use of _configure_ script. The usage of a separate package to just access the information placed into the Tcl library was also proposed. This was rejected too, due to the overhead for the management of the package in comparison to the small size of the code actually involved. Another proposal rejected in the early discussions was to have this TIP define an entire build system based upon Tcl. This TIP is certainly a step in this direction and facilitates the building of such a build system \(sic!\). Still, specifying such here was seen as too large a step right now, with too many issues to be solved and thus delaying the implementation of this TIP. Only the configuration of the particular variant of the Tcl library or extension which was generated is recorded in the library. No attempt is made to record the information required to allow the compilation of any possible variant of an extension. Doing so would reach again into the bigger topic of specifying a full build system. We've already established that as being out of the intended scope of this TIP. Note further that the scheme as specified above does not prevent us from adding the full information in a later stage. In other words, it does not restrict the development of a more powerful system in the future. This should be enough reasoning to allow the acceptance of even this admittedly simple system. The configuration information registered by Tcl is currently a very small subset of the information in _tclConfig.sh_. A future TIP is planned to provide the missing information in a regular and generalized manner. If an extension requires more information than provided by the Tcl configuration it will have to obtain this information itself. For instance, TclBlend requires a CLASSPATH, the name of a Java compiler, etc. whereas the TclPython and TclPerl extensions require paths to those environments, etc. It is not reasonable that the configure script for Tcl itself have to accommodate all requirements of all extensions of Tcl. Instead, the configure scripts or whatever other means is used to obtain the configuration information for the extensions should reflect their needs, and register the requirements gathered into their own configuration command. Note that an extension is only expected to create variables for information unique to it. Everything else can be had from the configuration command of Tcl and the extensions it depends on. This TIP is not in opposition to [[34]](34.md) but rather fleshes out one of the many details in the specification which were left open by that TIP. This TIP also does not propose to change the process for building Tcl itself. The goal is rather to make the building of extensions easier in the future. A naming convention for keys returned by the _config_ command would have been possible but would also require quite a lot more text, both in careful definition of the general categories and in explanations of the choices made. # Implementation Work on implementing this feature is tracked at Tcl Patch 507083 at the Tcl project at SourceForge. Implementation effort also takes place on the tip-59-implementation branch in the Tcl CVS repository \(see [[31]](31.md)\). # Copyright This document is in the public domain. |
Name change from tip/6.tip to tip/6.md.
|
| < | < | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 6: Include [Incr Tcl] in the Core Tcl distribution Author: Mark Harrison <[email protected]> State: Rejected Type: Project Vote: Done Created: 16-Oct-2000 Post-History: Tcl-Version: 8.4.0 ----- # Abstract Include [Incr Tcl] in the Core Tcl distribution. # Proposal [incr Tcl] <http://tcltk.com/itcl/> shall be included in the core Tcl distribution. It shall be included in the Tcl source tree, and built as part of the standard Tcl distribution. Specific items: * "itclsh" will not be included * "itcl\_\*" commands will not be included * everything will move from ::itcl to :: * the "find" subcommands will be reintegrated into "info" # Rationale The lack of a standard object and data abstraction system continues to hinder Tcl development. > "Lets face it, not including any sort of OO system is one of the major failings of Tcl. Indexing into global arrays is a sad hack when compared to a real OO system." _- Mo DeJong <[email protected]>_ Earlier this year, it seemed that it would finally be included in Tcl 8.4, but that plan was rescinded. Note that this is distinct from the "batteries included" \(BI\) distribution, and is not intended to be a model for building the BI distribution. It is a special case for inclusion in the core tcl command set, since a "class" command is a fundamental language construct. # Alternatives Include [incr Tcl] in a "batteries included" \(BI\) distribution. Many people will not opt for the BI distribution \([[4]](4.md)\) due to its larger size. It is quite likely that \(for example\) a Linux distribution my include Tcl as a standard component, but place the BI on a supplemental disk. # Objections _I don't want any object system included!_ You can delete the [incr Tcl] library with no harm to your code. _John Ousterhout hates objects!_ This misconception is primarily due to a misreading of one of his papers. A better summary of his position is that "scripting is a better solution than objects in many cases." John Ousterhout has told me that he will not stand in the way of adding object-oriented programming to Tcl. _[incr Tcl]'s object model is not good!_ [incr Tcl] supports the same object model as C\+\+ and Java. Many programmers are familiar with this model and accept it as a good model. _The CLOS object model is better!_ Quoting John Ousterhout, "People vote with their feet". For whatever reason, slot-based systems failed to gain as much popularity as C\+\+/Java-like systems. _There are many Tcl object systems to choose from!_ None are even a fraction as long-lived, popular, or well-supported as [incr Tcl]. # Special Provisions Since [incr Tcl] still exists as a separately named entity, this TIP shall not be construed as relieving any individual from the responsibility of providing appropriate [incr Apparel]. # Copyright This document has been placed in the public domain. |
Name change from tip/60.tip to tip/60.md.
|
| < | < | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | < > | | | < > | | | | | | < > | | | < > | | | | | | | | | | | | | | | | | | < > | | | < > | | | | | | | < > | | | < > | | | | | | | | | | | | | | > | 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 | # TIP 60: EXTERN Macro Change to Support a Wider Set of Attributes Author: David Gravereaux <[email protected]> Author: Donal K. Fellows <[email protected]> State: Rejected Type: Project Vote: Done Created: 06-Sep-2001 Post-History: Tcl-Version: 8.6 ----- # Abstract This TIP proposes a change to how the EXTERN macro in _tcl.h_ works to support a wider range of compiler specific attributes. # Rationale With working on Borland support recently, I found that luckily the newest "free commandline tools" <http://www.borland.com/bcppbuilder/freecompiler/> does support Microsoft's _\_\_declspec\(dllexport\)_ attribute. But at the same time, the older way with _\_\_export_ is still valid, but can't be used due to the order within the prototype declaration of the EXTERN macro. What's this with the MS compiler: __declspec(dllexport) __cdecl int func (int a, int b); will have to be this with Borland: int __export __cdecl func (int a, int b); The order of the attribute needs to be after the return type. Even though _\_\_declspec_ is supported in the Microsoft style with version 5.5\+ of the Borland compiler, if EXTERN could swap around the order a hair, old Turbo C v5.0 has a better chance to make a DOS library. Should someone feel the need. Let's leave the existing EXTERN macro as-is and just make a new one called TCL\_EXTERN to support the new behavior. Karl Lembuaer \(sp?\) did a presentation @ OSCON regarding his recent tinytcl project _%TODO: add link here%_ about his DOS port of Tcl 6.7 for use in a hand-held device. Stepping backward for DOS support, may actually be a leap forward in an off-beat manner... # Rejected Alternatives I saw something like this in a very old DDE extension that someone at Sun wrote. It was used as an example windows extension for years. ftp://tcl.activestate.com/pub/tcl/misc/example.zip In example.h is this: #if defined(__WIN32__) # if defined(_MSC_VER) # define EXPORT(a,b) __declspec(dllexport) a b # else # if defined(__BORLANDC__) # define EXPORT(a,b) a _export b # else # define EXPORT(a,b) a b # endif # endif #else # define EXPORT(a,b) a b #endif EXTERN EXPORT(int,Example_Init) _ANSI_ARGS_((Tcl_Interp *interp)); That work is doing the same job, but I prefer the method that I'm proposing. It is also mentioned on <http://tcl.activestate.com/doc/howto/winext.html> and feel it is rather out-of-date and the order issue with _\_\_export_ should be brought into the core with this patch and be fix for good. Is> EXTERN int Foobar_Init (Tcl_Interp *interp); Proposed> TCL_EXTERN(int) Foobar_Init (Tcl_Interp *interp); # Reference Implementation <https://sourceforge.net/tracker/download.php?group\_id=10894&atid=310894&file\_id=70480&aid=436116> # Examples Is: EXTERN int Foobar_Init (Tcl_Interp *interp) { #ifdef USE_TCL_STUBS if (Tcl_InitStubs(interp, "8.1", 0) == NULL) { return TCL_ERROR; } #endif Tcl_CreateObjCommand(interp, "foobar", FooBar, NULL, NULL); return TCL_OK; }; Proposed: TCL_EXTERN(int) Foobar_Init (Tcl_Interp *interp) { #ifdef USE_TCL_STUBS if (Tcl_InitStubs(interp, "8.1", 0) == NULL) { return TCL_ERROR; } #endif Tcl_CreateObjCommand(interp, "foobar", FooBar, NULL, NULL); return TCL_OK; }; Preprocessor output is the following: > Borland: /* foobar.c 14: */extern int __export /* foobar.c 15: */Foobar_Init (Tcl_Interp *interp) /* foobar.c 16: */{ /* foobar.c 17: */ /* foobar.c 18: */if (Tcl_InitStubs(interp, "8.1", 0) == 0) { /* foobar.c 19: */return 1; /* foobar.c 20: */} /* foobar.c 21: */ /* foobar.c 22: */(tclStubsPtr->tcl_CreateObjCommand)(interp, "foobar", FooBar, 0, 0); /* foobar.c 23: */return 0; /* foobar.c 24: */}; > VC\+\+: extern __declspec(dllexport) int Foobar_Init (Tcl_Interp *interp) { if (Tcl_InitStubs(interp, "8.1", 0) == ((void *)0)) { return 1; } #line 22 "foobar.c" (tclStubsPtr->tcl_CreateObjCommand)(interp, "foobar", FooBar, ((void *)0), ((void *)0)); return 0; }; > MinGW \(native gcc on win\): extern int Foobar_Init (Tcl_Interp *interp) { if (Tcl_InitStubs(interp, "8.1", 0) == ((void *)0) ) { return 1 ; } (tclStubsPtr->tcl_CreateObjCommand) (interp, "foobar", FooBar, ((void *)0) , ((void *)0) ); return 0 ; }; # Random Notes In _tclInt.h_ starting around line 1916, are prototypes for the internal cmdprocs. I can't think of any reason why they should be exported. Also note the comment about line:1673, as it states: /* *---------------------------------------------------------------- * Procedures shared among Tcl modules but not used by the outside * world: *---------------------------------------------------------------- */ As the current EXTERN macro places ""everything"" exportable, the use of EXTERN following this comment in _tclInt.h_ is contradictory. In place of EXTERN for this purpose I used the new TCL\_EXTRNC in the reference implementation. # Copyright This document has been placed in the public domain. |
Name change from tip/61.tip to tip/61.md.
|
| < | < | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 61: Make TK_NO_SECURITY Run-Time Switchable Author: Jeff Hobbs <[email protected]> Author: Donal K. Fellows <[email protected]> State: Deferred Type: Project Vote: Pending Created: 12-Sep-2001 Post-History: Tcl-Version: 8.5 ----- # Abstract This TIP changes the compile time Tk define TK\_NO\_SECURITY to be switchable at run-time. # Rationale The TK\_NO\_SECURITY compile time \#define is available to disable some security checking when send is used. The direct comments in the Makefile are: # To turn off the security checks that disallow incoming sends when # the X server appears to be insecure, reverse the comments on the # following lines: SECURITY_FLAGS = #SECURITY_FLAGS = -DTK_NO_SECURITY I propose to make this switch configurable at runtime through a _tk securesend_ option. # Benefits Users would be able to debug between Tk applications on Unix using _send_ without having to compile a special version of Tk or manipulating the security settings of their X server to Tk's liking \(which can then conflict with other work\). It is common for users in internal \("safe"\) networks to open up access to an X server with _xhost \+machine_. # Drawbacks By allowing security to be disabled, users do possibly open up their system to attack. However, secure is the default setting, and any paranoid users can _rename send \{\}_ to ensure that it is not used at all. # Reference Implementation A full patch for this feature is available at: <http://sf.net/tracker/?func=detail&aid=456732&group\_id=12997&atid=312997> The proposal adds one element to the private _TkDisplay_ structure \(configuration for secure send is done per display\), and creates the Tcl level command: tk securesend ?-displayof window? ?boolean? It leaves the TK\_NO\_SECURITY flag alone. If specified, send is insecure by default, otherwise it is secure. # Comments _DKF_ - It should be possible to control the setting of the compile-time TK\_NO\_SECURITY flag from the _configure_ script; having to edit the Makefile by hand to adjust it makes it too easy to inadvertently break something by introducing an unfortunate typo. Being able to pass a _--disable-security_ flag would make thing much easier from a user's point of view, and will make it less likely that the Tk maintainers will have to deal with bug reports that ultimately stem from a dumb mistake made in a sensitive spot... # Copyright This document has been placed in the public domain. |
Name change from tip/62.tip to tip/62.md.
|
| < | < | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | < > | | | | < > | | | | | | | | | | | | | | | | | | | | | < > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | < > | | | < < < | > > > | > | 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 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 | # TIP 62: Add Support for Command Tracing Author: Hemang Lavana <[email protected]> Author: Vince Darley <[email protected]> State: Final Type: Project Vote: Done Created: 18-Sep-2001 Post-History: Tcl-Version: 8.4 ----- # Abstract This TIP proposes that the Tcl's trace command be extended to include the following features: 1. tracing of command execution for the specified tcl command, and 2. step-wise tracing of any command execution within a specified procedure. # Rationale One of the main strengths of Tcl is the ability to trace _read_, _write_ or _delete_ operations on variables. Moreover, Tcl8.4 has already added support for tracing _rename_ or _delete_ operations on Tcl commands. Addition of the proposed subcommand for tracing executions will further improve the capabilities of Tcl without any loss of performance \(see _Benchmark Results_ section below\). I can see several applications of this feature, including: * overloading/wrapping of Tcl commands, please see <http://mini.net/tcl/1494.html> * aid developer in debugging Tcl scripts * profiler module in _tcllib_ can benefit from this feature # Specification This TIP proposes an enhancement to the trace command with the following syntax: trace add execution name ops command The type _execution_ is used to arrange for _command_ to be executed whenever the command _name_ is invoked for execution. _Name_ may refer to any of the tcl commands or procedures that have been previously defined. It is an error to create an _execution_ trace on a non-existant command or a procedure. The _ops_ argument can accept _enter_, _leave_, _enterstep_, and _leavestep_ as valid operations: 1. _enter_ - Invoke _command_ whenever the command _name_ is executed, just before the actual execution takes place. 2. _leave_ - Invoke _command_ whenever the command _name_ is executed, just after the actual execution takes place. 3. _enterstep_ - Invoke _command_ for every tcl command which is executed inside the procedure _name_, just before the actual execution takes place. Setting a _enterstep_ trace on a _command_ will not result in an error and is simply ignored. 4. _leavestep_ - Invoke _command_ for every tcl command which is executed inside the procedure _name_, just after the actual execution takes place. Setting a _leavestep_ trace on a _command_ will not result in an error and is simply ignored. When the trace triggers, depending on the operations being traced, a number of arguments are appended to command so that the actual command is as follows: For _enter_ and _enterstep_ operations: command command-string op _command-string_ gives the complete current command being executed, including all arguments in their fully expanded form. _Op_ indicates what operation is being performed on the variable, and is one of _enter_ or _enterstep_ here. The trace operation can be used to stop the command from executing, by deleting the command in question. Of course when the command is subsequently executed, an 'invalid command' error will occur. For _leave_ and _leavestep_ operations: command command-string code result op _command-string_ gives the complete current command being executed, including all arguments in their fully expanded form. _code_ gives the result code of that execution, and _result_ gives its result string. _Op_ indicates what operation is being performed on the variable, and is one of _leave_ or _leavestep_ here. _Command_ executes in the same context as the code that invoked the traced operation: thus the _command_, if invoked from a procedure, will have access to the same local variables as code in the procedure. This context may be different than the context in which the trace was created. If _command_ invokes a procedure \(which it normally does\) then the procedure will have to use upvar or uplevel commands if it wishes to access the local variables of the code which invoked the trace operation. Note that if the value of a local variable is passed as an argument to the traced command _name_ and is modified by the _command_ procedure, the traced command _name_ will still be invoked with the old value of the local variable. This is because the argument list to _name_ is formed before the traced _command_ is invoked. Please see the section on _Future Scope_ below on how to modify the arguments passed to _name_. While _command_ is executing during an _execution_ trace, traces on _name_ are temporarily disabled. This allows the _command_ to execute _name_ in its body without invoking any other traces again. If an error occurs while executing the _command_ body, then the command _name_ as a whole will return that same error. Therefore, if _catch_ command is used for invocation of the _name_ command, it will also ignore errors resulting from such traces. When multiple traces are set on _name_, then the sequence of trace command invocation is as follows: 1. For _enter_ and _enterstep_ operations, the traced commands are invoked in the reverse order of how these traces were created. 2. For _leave_ and _leavestep_ operations, the traced commands are invoked in the same order as how these traces were created. For example, if we have two traces on proc foo: trace add execution foo {enter leave} {barA} trace add execution foo {enter leave} {barB} then the trace commands _barA_ and _barB_ will be invoked in the following sequence: barB {foo x} {enter} barA {foo x} {enter} foo x barA {foo x} 0 {} {leave} barB {foo x} 0 {} {leave} The creation of many _enterstep_ or _leavestep_ traces can lead to unintuitive results, since the invoked commands from one trace can themselves lead to further command invocations for other traces. However, these unintuitive results are completely predictable and safe \(and tested in the test suite\). Nevertheless the user will probably only want to have one such trace active at a time. Once created, the trace remains in effect either until the trace is removed with the _trace remove execution_ command, until the _name_ is deleted or until the interpreter is deleted. Note that renaming the command _name_ will not remove the execution traces. To implement _enterstep_ and _leavestep_ traces, it is necessary to invoke traces regardless of at what level the _command_ is being traced. This means that the value for _level_ argument to Tcl\_CreateTrace and Tcl\_CreateObjTrace APIs should also accept _0_. A value of _0_ implies that commands at all levels will be traced. # Examples The following script defines a procedure _foo_ and illustrates several cases as to how its execution can be traced. # Define the proc foo proc foo {var} { return [string index $var [expr {$var*2}]] } # Command to invoke on trace activation proc print {args} { puts stdout "PRINT: $args" } proc main {} { puts stdout "================CASE 1=========================" puts stdout "Trace proc foo only" trace add execution foo {enter leave} {print exec} foo 4 puts stdout "================CASE 2=========================" puts stdout "Trace proc foo as well as all commands within it" trace add execution foo {enterstep leavestep} {print step} foo 4 # Remove all traces trace remove execution foo {enter leave} {print exec} trace remove execution foo {enterstep leavestep} {print step} puts stdout "================CASE 3=========================" puts stdout "Add a trace on string command" trace add execution string {enter leave} {print exec} foo 4 trace remove execution string {enter leave} {print exec} } main The expected output of running the above script would be: ===================CASE 1======================== Trace proc foo only PRINT: exec {foo 4} enter PRINT: exec {foo 4} 0 {} leave ===================CASE 2======================= Trace proc foo as well as all commands within it PRINT: exec {foo 4} enter PRINT: step {expr {$var*2}} enterstep PRINT: step {expr {$var*2}} 0 8 leavestep PRINT: step {string index 4 8} enterstep PRINT: step {string index 4 8} 0 {} leavestep PRINT: step {return {}} enterstep PRINT: step {return {}} 2 {} leavestep PRINT: exec {foo 4} 0 {} leave ===================CASE 3======================= Add a trace on string command PRINT: exec {string index 4 8} enter PRINT: exec {string index 4 8} 0 {} leave Case 1 specifies a enter and leave trace on proc foo. Here the proc foo is fully byte-code-compiled. Case 2 additionally invokes a enterstep and leavestep trace on proc foo. This means that it will trace each command that is inovked within the proc foo. Here the proc foo is \*not\* byte-code-compiled. This is implemented by setting the DONT\_COMPILE\_CMDS\_INLINE flag. Case 3 specifies a trace on string command only. Here all commands within proc foo, except string command, is byte-code-compiled. This is implemented by modifying compilation engine to check for CMD\_HAS\_EXEC\_TRACES flag before generating any byte-code. # Reference Implementation This proposal was originally implemented by Vince Darley. Please see Feature Request \#462580: <http://sf.net/tracker/?func=detail&aid=462580&group\_id=10894&atid=360894> The original patch from Vince Darley has been modified in the following respects: 1. For _enter_ and _enterstep_ operations, the original patch passed arguments to the _command_ in its unexpanded form. This behavior has been changed to pass the arguments in its fully expanded form since it should be more useful for debugging scripts. 2. The original patch could not trace Tcl commands that were invoked inside a procedure because tracing is currently not possible for compiled commands. Therefore, the patch was modified such that Tcl commands are no longer internally compiled if a trace has been set on a command. 3. For multiple traces on same command, the original patch invoked the traces in the same order as they were created. This behavior was changed so that for _enter_ and _enterstep_ operations, the traces are invoked in the reverse order of its creation. For _leave_ and _leavestep_, the traces are still invoked in the original order. 4. The original patch was created on 2000-Sept-14. It was updated to work with the current CVS head. The latest patch for this tip 62 is available at: <http://www.employees.org/~hlavana/tcl/> The main changes for the patch are described in brief next. Two new flags have been defined in tcl.h: #define TCL_TRACE_ENTER_EXEC 1 #define TCL_TRACE_LEAVE_EXEC 2 These flag values are passed to Tcl\_CreateObjTrace and used by command execution traces. More internal flags for slots 4, 8, 15, 16, 32 are defined in tclCmdMZ.c file: TCL\_TRACE\_ENTER\_DURING\_EXEC, TCL\_TRACE\_LEAVE\_DURING\_EXEC, TCL\_TRACE\_ANY\_EXEC, TCL\_TRACE\_EXEC\_IN\_PROGRESS and TCL\_TRACE\_EXEC\_DIRECT. A new function TclTraceExecutionObjCmd function implements the _trace \{add\|remove\|list\} execution ..._ subcommands. A new function TclCheckExecutionTraces is defined to check for traces added by the execution subcommand. A new function TclCheckInterpTraces is defined to check for global traces added by the Tcl\_CreateObjTrace command. The TclEvalObjvInternal has been modified to call the above two functions before as well as after the original command is executed. A new function TraceExecutionProc is invoked, when necessary, to execute the actual trace command in the interpreter. A new structure ActiveInterpTrace has been defined for internal use so that it behaves reasonably when traces are deleted while active. In tclVar.c file, the function CallTraces has been renamed to CallVarTraces and iPtr->activeTracePtr has been renamed to iPtr->activeTraceVarPtr. An additional check for \(tracePtr->level == 0\) has been added in Tcl\_EvalObjv and TclExecuteByteCode functions, so as to enable command tracing at all levels. # Benchmark Results The benchmark results corresponds to _Version 1.1_ of the reference implementation. One potential objection to this TIP could be that it may affect the performance of the Tcl-core. Therefore, I have run the _runbench.tcl_ script from the tclbench module for comparison on a Sun Ultra5, Solaris2.6 machine. The results have been posted at <http://sf.net/tracker/?func=detail&aid=462580&group\_id=10894&atid=360894> These results show that there is hardly any performance hit, if any, by addition of this feature. Of course when you activate a trace on a command, then you will see a performance hit, but since primary uses of traces will be in profiling and debugging, that isn't an issue. # Future Scope This proposal does not allow for the trace invocation _command_ to do the following: 1. modify the number of arguments passed to _name_ 2. modify the value of arguments passed to _name_ 3. modify the result value and result code returned by _name_ 4. skip invocation of _name_ altogether if desired. Consider the example of adding a sub-command "string reverse ..." as shown on <http://mini.net/tcl/1570.html.> Instead of using the rename command, it should be possible to use the trace command to do the same, as follows: trace add execution string {enter} {::mylib::stringx} proc ::mylib::stringx {subcmd args} { switch -exact -- $subcmd { "reverse" { # Hmm ... this is my subcommand, process it here set returnValue [code_to_reverse_string_value] # We need a mechansim to return immediately here # with the processed results and an appropriate # code value and not invoke the original string command. } default { # This is probably a vaild subcommand, so do nothing # and let the original string command handle it } } } # Copyright This document has been placed in the public domain. |
Name change from tip/63.tip to tip/63.md.
|
| < | < | | | | | | | > | | | | | | | | | | | | | | | | > | 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 | # TIP 63: Add -compound Option to Menu Entries Author: Vince Darley <[email protected]> State: Final Type: Project Vote: Done Created: 27-Sep-2001 Post-History: Tcl-Version: 8.4 ----- # Abstract This TIP adds to menu entries the ability to display both textual labels and images \(or bitmaps\) in exactly the same way as buttons and menubuttons currently can, by adding a _-compound_ option. # Rationale Menu entries are very similar to labels in most respects, but they currently lack the ability to show an image and a piece of text at the same time. It is a useful piece of functionality currently missing from Tk \(certainly many standard applications make use of such menu entries, e.g. Internet Explorer\). The changes involved are relatively small. A very similar TIP [[11]](11.md) was accepted without much argument. # Proposal This TIP implements the change by adding an additional option _-compound_ to menu entries which behaves identically to Tk's existing _-compound_ option: it accepts the values _none_, _center_, _left_, _right_, _top_, and _bottom_, and controls the relative placement of an image to the text label in the entry. A reference implementation exists, and is available from: ftp://ftp.ucsd.edu/pub/alpha/tcl/compoundmenu.diff \(note this diff has Windows-style line endings\). This implementation is known to work on Windows and Unix, and since the changes are very, very similar on MacOS I expect it to work there \(except perhaps for simple editing mistakes\). # Copyright This document has been placed in the public domain. |
Name change from tip/64.tip to tip/64.md.
|
| < | < | | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 64: Improvements to Windows Font Handling Author: Chris Nelson <[email protected]> Author: Kevin Kenny <[email protected]> State: Deferred Type: Project Vote: Done Created: 27-Sep-2001 Post-History: Tcl-Version: 8.4 Obsoleted-By: 145 ----- # Abstract This TIP improves handling of native fonts in Tk under Microsoft Windows making Tk applications more aesthetic and more consistent with users' expectations of 'Windows applications. # Background Tk 8.4 includes platform-specific system font names which relate to configurable aspects of the native system. * On UNIX, this includes all X font names \(e.g. as listed by _xlsfonts_\). * On Macintosh, this includes _system_ and _application_. * On Microsoft Windows, this includes _system_, _systemfixed_, _ansi_, _ansifixed_, _device_, and _oemfixed_. Through v8.4a3, Tk used 8pt MS Sans Serif as the default font for widgets. While this was almost OK, it fails in two respects: * Users can change the font used for various 'Windows desktop features so MS Sans Serif may not be the correct font for, for example, menus. * Windows 2000 and Windows XP use Tahoma, not MS Sans Serif as their default font. SourceForge patch \#461442 \(Make Tk use the default Windows font\) <http://sf.net/tracker/?func=detail&aid=461442&group_id=12997&atid=312997> attempts to address Tk's deficiency by adding a _windefault_ font based on the Message font configured for the Windows desktop. This appears to be wrong. This TIP attempts to fix the default Tk font the right way as well as giving Tk programmers access to the rest of the fonts configured for the 'Windows desktop. NOTE: RFE 220772 on SourceForge <http://sf.net/tracker/?func=detail&aid=220772&group_id=12997&atid=362997> has a related patch. # The Default GUI Font The Win API call _GetStockObject\(\)_ accesses brushes, pens, and fonts which are pre-configured on the system. The available fonts are: 1. ANSI\_FIXED\_FONT 2. ANSI\_VAR\_FONT 3. DEVICE\_DEFAULT\_FONT 4. DEFAULT\_GUI\_FONT 5. OEM\_FIXED\_FONT 6. SYSTEM\_FIXED\_FONT 7. SYSTEM\_FONT The _TkStateMap systemMap_ in _tkWinFont.c_ listed all but one of these, DEFAULT\_GUI\_FONT. As it turns out, this is the most important as it is the one that 'Windows uses as it's default font \(for example, in Control Panel Applets\). I propose to add DEFAULT\_GUI\_FONT to the _systemMap_ with a font name of _defaultgui_ and to change CTL\_FONT in _tkWinDefault.h_ from _\{MS Sans Serif\} 8_ to _defaultgui_. This will require a change in documentation to list the new system font name but is otherwise simple and painless. Furthermore, it makes Tk GUIs look right on W2k. A reference implementation for this is available in patch 461442 \(referenced above\). # Access to Desktop Fonts The original implementation of _windefault_ as a new font, accessed the message font from the NONCLIENTMETRICS structure. While this is not, in fact, the correct default GUI font, it is an important system font, as are the others on the NONCLIENTMETRICS structure. The structure lists: * Caption \(title bar\) font * Small Caption \(palette title bar\) font * Menu font * Tooltip \(and status bar\) font * Message box font The 'Windows Desktop Properties also include a font for icon labels on the desktop. This font is accessed with _SystemParametersInfo\(\)_. I propose to add 6 desktop fonts as system fonts on Windows. The names would be derived from their Desktop Properties entries: _dtIcon_, _dtTitleBar_, _dtMenu_, _dtMessageBox_, _dtPaletteTitle_, _dtToolTip_. The "dt" prefix associates the fonts with the desktop properties. \(Can or should font names have internal capital letters?\) We might also add synonyms which relate to the structure field names and/or customary use of the font. I'd propose adding _dtCaption_ as equivalent to _dtTitleBar_, _dtSmallCaption_ as equivalent to _dtPaletteTitle_, and _dtStatus_ as equivalent to _dtToolTip_. A reference implementation for this is available in Patch \#461442 \(referenced above\) albeit with different font names. # Dynamic fonts Many 'Windows applications respond on-the-fly to changes in the desktop fonts. Tk responds to changes in Tk fonts via [font configure]. I propose that Tk respond to the WM\_SETTINGCHANGE message from Windows to propagate changes to the desktop fonts enumerated above as it propagates changes to Tk fonts when they are reconfigured. I have yet to prototype these changes. # Comments _KBK_ wonders whether the dt\* fonts have logical counterparts on the other platforms \(KDE, Gnome/Gtk, Macintosh, HP-VUE, ...\) and if implementors on those platforms might want to try to mirror this functionality. Since nobody has commented, he assumes that they at least do not find the idea objectionable. # Copyright This document has been placed in the public domain. |
Name change from tip/65.tip to tip/65.md.
|
| < | < | | | | | | | | | > | | | | | | | | | | | | | | | | | | | | < < > > | < > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 65: Enhanced [info args] Author: Glenn Jackman <[email protected]> Author: Don Porter <[email protected]> Author: Glenn Jackman <[email protected]> State: Rejected Type: Project Vote: Done Created: 18-Sep-2001 Post-History: Tcl-Version: 8.5 ----- # Abstract This TIP proposes a new subcommand to the [info] command be added that would return the list of arguments, together with any default values in the same format as the _args_ parameter to the [proc] command. # Introduction The [proc] man page defines _args_ as: > ... the formal arguments to the procedure. It consists of a list, possibly empty, each of whose elements specifies one argument. Each argument specifier is also a list with either one or two fields. If there is only a single field in the specifier then it is the name of the argument; if there are two fields, then the first is the argument name and the second is its default value. Suppose we define a procedure like this: proc test {one {two 2} {three {3 4 5}} args} {return} We want to determine the formal arguments for this procedure. We want some method to return the list: one {two 2} {three {3 4 5}} args [info args] fails us because it does not return default values, only the list of argument names \{one two three args\}. The [info default] command exists, and does partially what we want. However [info default] only operates on a single argument. To determine the complete list of arguments with default values, we must iterate over the arguments returned by [info args]. We would define a procedure like: proc info_args_with_defaults {procname} { set argspec [list] # [info args] throws an error if $procname is not a procedure. foreach arg [info args $procname] { if {[info default $procname $arg value]} { lappend argspec [list $arg $value] } else { lappend argspec $arg } } return $argspec } info_args_with_defaults test ;# ==> returns {one {two 2} {three {3 4 5}} args} A more sophisticated scripted solution is to overload the [info] command itself, as described in the Wiki at <http://wiki.tcl.tk/wrappingCommands> It would be much more convenient to be able to rely on the [info] command itself to return the desired information, particularly since it _almost_ does what we want already. _This topic was originally raised in the news:comp.lang.tcl newsgroup in the thread <http://groups.google.com/groups?th=4b0d5dba85d2c160_> # Specification Add [info formalargs] to the set of subcommands for Tcl's built-in [info] command, with syntax: info formalargs $procName This command will raise an error if _$procName_ is not the name of a proc. Otherwise, it will return a list of formal arguments of the named proc, along with their default values, if any, in a format suitable for passing to the [proc] command as a second argument. # Rationale With the goal of maintaining backwards compatibility in mind, two possibilities arise: adding a new switch to the existing [info args] command, and adding a completely new subcommand to [info]. Adding a switch to [info args] may break backwards compatibility. If we use the syntax [info args _?-withdefaults? procname_], there may be trouble with existing scripts containing a procedure named "-withdefaults". The syntax [info args _procname ?-withdefaults?_] is completely backwards compatible. However, among Tcl commands that take subcommands, there is currently some inconsistency as to where switches should appear. [clock] subcommands place these options after required parameters. [namespace] and [package] subcommands place these options before required parameters. Some [file] subcommands put them before, some after. Currently, no [info] subcommands take switches. Rather than compound to this inconsistency, creating a new [info] subcommand feels cleaner. Possible names include: argspec, arglist, args\_with\_defaults: These all collide with the "arg", "ar", "a" shorthands for [info args _procname_]. And _args\_with\_defaults_ is just \*way\* too ugly. formalargs, fullargs: Either of these could be used. This collides with the "f" shorthand for [info functions] parameters: This collides with the "pa" shorthand for [info patchlevel] prototype: This collides with the "pro" and "pr" shorthands for [info procs _?pattern?_] signature: This could be used, as it does not collide with any shorthand for either [info script] or [info sharedlibextension]. The term "signature" has meaning in the Java and C\+\+ worlds: the function name and its arguments together comprise the signature. The purpose of this TIP is to return only the arguments with any defaults, so to avoid any potential confusion I will rule out "signature". Of the remaining possibilities, my choice would be "formalargs". The term "formal arguments" is used in the [proc] man page. "formalargs" also incorporates the word "args", indicating a relationship to [info args]. # Reference Implementation Refer to the submitted patch, which implements an subcommand named [info fullargs], at: <http://sourceforge.net/tracker/index.php?func=detail&aid=461635&group\_id=10894&atid=310894> # Reasons for Rejection Those voting against this proposal believed that since the desired functionality is already possible with a short script of just a few Tcl commands, it would be unnecessary bloat to add another subcommand. Some also pointed to [[112]](112.md) as another approach to letting people extend Tcl built-in commands with their own custom subcommands. # Copyright This document has been placed in the public domain. |
Name change from tip/66.tip to tip/66.md.
|
| < | < | | | | | | | > | | | | | | 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 | # TIP 66: Stand-alone and Embedded Tcl/Tk Applications Author: Arjen Markus <[email protected]> State: Draft Type: Informative Vote: Pending Created: 02-Oct-2001 Post-History: Keywords: installation,initialisation,embedded,resources ----- # Abstract This TIP describes the development and deployment of Tcl/Tk applications, with particular attention on how to _embed_ the interpreter into executables written in C or C\+\+. # Introduction and Background Usually, an application that uses Tcl/Tk in some way uses an independent installation and the application itself is started via a standard shell, like _tclsh_ or _wish_. There are numerous occasions when such a set-up is not convenient: * Installation of external software is not allowed unless the IT department at the client's site consents - a very reasonable approach to the uncountable problems that occur due to conflicting software in modern computing environments. |
︙ | ︙ | |||
48 49 50 51 52 53 54 | application using one of the commercial tools that are available for this arcane job, we ran into a bizarre limitation: text replacement was possible for the so-called Windows INI-files only, but not for other types of files. The text to be replaced was the name of the installation directory. After several trials with the programming constructs the tool allowed, we chose a much better solution: a small Tcl script wrapped into a stand-alone program | | | | | 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 | application using one of the commercial tools that are available for this arcane job, we ran into a bizarre limitation: text replacement was possible for the so-called Windows INI-files only, but not for other types of files. The text to be replaced was the name of the installation directory. After several trials with the programming constructs the tool allowed, we chose a much better solution: a small Tcl script wrapped into a stand-alone program using Freewrap. \(The application itself now actually uses another stand-alone Tcl script to take care of the file management that was too complicated for ordinary DOS batch files.\) 2. The second example involves a small program that proves the usefulness of Tcl/Tk in on-line visualisation. The idea there is that large computational programs can send their data at regular steps during the computation to a separate program that plots these results in some meaningful way. To achieve this the program exports the results to the Tcl interpreter which uses the socket command to send them to a \(primitive\) viewer. For demonstration purposes you must be able to copy the program along with some files it needs on an arbitrary computer and, later, remove it with just a little effort. Applications that use Tcl/Tk as an embedded library to achieve their goals, rather than exist as extensions or applications written in Tcl, can be quite useful. Examples include on-line visualisation in large |
︙ | ︙ | |||
83 84 85 86 87 88 89 | environment? * What you can and can not do with a bare interpreter? * How to enhance its capabilities, such that it works as in an ordinary Tcl shell? | | | | | | | | | | | | | | | | | | | | | | | 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 | environment? * What you can and can not do with a bare interpreter? * How to enhance its capabilities, such that it works as in an ordinary Tcl shell? * What \(binary and script\) libraries are required? * How to deal with other programming languages than C/C\+\+? * How to create applications that can be installed without an independent Tcl installation? # Related TIPs and Discussions The are several TIPs at the moment of this writing that are in some way related to the subject: * [[4]](4.md) proposes to outline the release and distribution philosophy, so that it becomes easy to include generally useful extensions - the so-called "batteries included". * [[12]](12.md) focuses completely on the "batteries included" aspect of the source distribution. * [[34]](34.md) is intended to solve some of the more awkward issues of TEA, as the current build system actually requires separate versions for UNIX and Windows. * [[55]](55.md) defines the set-up of packages that can be automatically installed into an existing installation. * Postings on the news:comp.lang.tcl newsgroup frequently involve how to embed Tcl into a C application, with an emphasis on loading packages and the use of the _Tcl\_Init\(\)_ function. * Recently discussions have been held about supporting programming languages other than C. Notably: Pascal, FORTRAN, Visual Basic. # Contents of the Planned Document The document that should help programmers with the issues discussed here will have the following \(tentative\) table of contents: * Introduction, outlining its purpose. * Tcl's bootstrap procedure, describing how the usual shells work. * Creating interpreters, what a bare interpreter can and can not do, how to enrich it via start-up scripts like _init.tcl_. * Compiling and linking, the usual issues surrounding the making of a binary executable. * Interfacing to other programming languages, though possibly a huge subject, it will present some guidelines, both practical implementation and design issues. * Installation and deployment, should inform about the external resources \(environment variables, libraries, etc\) for the application. * Overview, provide a checklist of the various possibilities and how to achieve them, with pointers for further information. * Literature, all the good books and other references. ---- # Discussion Issues that arise are: * what is the simplest way to embed Tcl, * what resources are needed \(in terms of script and binary libraries\) by such an application, * how can the application find everything it needs? This TIP is meant to be a document that enables programmers who do not have intimate knowledge of the Tcl core to build such application and deploy them in the way they want. Should it turn out that some automated tool would be nice to help the programmers, then this TIP will also cover such a tool. ---- # Using the Tcl library There are numerous ways an application written mainly in a language like C can use the Tcl and Tk libraries \(in short: Tcl\): * The application can simply use Tcl as a convenient library of C routines. In that case, Tcl would provide such facilities as regular expressions or channels. * The application can use Tcl as a scripting tool, that is, it will call Tcl to evaluate scripts and import the results. * The application can use Tcl in a more complicated mixture: Tcl scripts get evaluated that require binary extensions \(both defined outside the application and as an integral part of the application\). * An application that uses Tcl need not be written in C, but could be written in any programming language that allows calls to and from C routines directly or indirectly. _Note:_ due to the fact that the author is mostly familiar with the UNIX/LINUX and Windows platforms, no comments will be made about the Macintosh. This is completely due to ignorance, not to arrogance. In principle, using the Tcl/Tk libraries is very simple: just create a Tcl interpreter, fill it with variables, commands and so on and feed it scripts, either as a file or as a string. It gets more complicated in the following situations: * The interpreter must be able to handle packages and interact with the environment in much the same way as tclsh or wish. * The application needs to intermix its own processing with Tcl event loops \(such as continuing a calculation while a Tk window shows the progress\). * It must be possible to use the application independently from a full Tcl installation. The key to a successful implementation is: understanding how to properly initialise Tcl. |
︙ | ︙ | |||
225 226 227 228 229 230 231 | and the output. Let us assume that the application is written in some convenient programming language like C. The reasons for using Tcl are: * Flexible input routines | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | < < > > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | < > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | < > | | | | | | | | | | | | | | | | | > | 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 | and the output. Let us assume that the application is written in some convenient programming language like C. The reasons for using Tcl are: * Flexible input routines > By using the scripting capabilities of Tcl one can easily adapt the program to the input file or files that it should read. * Flexible output routines > Again, the scripting capabilities allow adapting the output to the customer's wishes, without having to recompile and link it. This can be done for simple files on disk, but also graphical output or storage in a database is possible, _without changing the program itself_. # The simplest way: create a bare interpreter With the Tcl routine Tcl\_CreateInterp\(\) you can create an interpreter that is capable of all the basic commands: Tcl_Interp * interp ; char * input_filename ; char * buffer ; double x, y, z ; /* Create the interp, use it to read the given input file, Note: Using the string API for simplicity, no error checking */ interp = Tcl_CreateInterp() ; Tcl_SetVar( interp, "input_file", input_filename, TCL_GLOBAL_ONLY ) ; Tcl_EvalFile( interp, startup_script ) ; /* Extract the input data */ buffer = Tcl_GetVar( interp, "x", TCL_GLOBAL_ONLY ) ; Tcl_GetDouble( interp, buffer, &x ) ; buffer = Tcl_GetVar( interp, "y", TCL_GLOBAL_ONLY ) ; Tcl_GetDouble( interp, buffer, &y ) ; buffer = Tcl_GetVar( interp, "z", TCL_GLOBAL_ONLY ) ; Tcl_GetDouble( interp, buffer, &z ) ; /* Destroy the interp - if you do not need it any longer */ Tcl_DestroyInterp( interp ) ; The output routine contains a similar fragment \(note, we assume the Tcl interpreter was stored somewhere\): Tcl_Interp * interp ; char * output_filename ; char buffer[TCL_DOUBLE_SPACE] ; double a, b ; /* Export the results to the interpreter */ Tcl_PrintDouble( interp, a, buffer ) ; Tcl_SetVar( interp, "a", buffer, TCL_GLOBAL_ONLY ) ; Tcl_PrintDouble( interp, b, buffer ) ; Tcl_SetVar( interp, "b", buffer, TCL_GLOBAL_ONLY ) ; Tcl_SetVar( interp, "output_file", input_filename, TCL_GLOBAL_ONLY ) ; Tcl_EvalFile( interp, report_script ) ; To add error checking \(always do!\), use code like this: Tcl_Channel errChannel ; if ( Tcl_EvalFile( ... ) != TCL_OK ) { errChannel = Tcl_GetStdChannel( TCL_STDERR ) ; if ( errChannel != NULL ) { TclWriteObj( errChannel, Tcl_GetObjResult(interp) ) ; TclWriteChars( errChannel, "\n", -1 ) ; ... /* Quit the program or other error handling? */ } } With this approach you need only to worry about the Tcl binary libraries: if the dynamic versions are linked to your application, then distribution of your application should include these binaries. If, on the other hand the static versions are used, your application already contains all of Tcl it needs all by itself. The limitations of this approach are: * The utilities ordinarily defined via the Tcl initialisation script _init.tcl_ are not available. \(Note that these include such procedures as _tclPkgSetup_ and _unknown_\) * The Tcl variables _argc_, _argv_ and _argv0_ are not set. This may be problematic if you want to use these variables to communicate with the user, e.g. provide an initial script file on the command-line. * Character encodings are not available. This will limit your application to ASCII characters. # Complete initialisation: the role of init.tcl The next section outlines the full initialisation procedure that is used in the standard _tclsh_ shell. This section concentrates instead on some practical observations: * The routine Tcl\_FindExecutable\(\) does a lot more than its name suggests: it is responsible for initialising the various subsystems in a controlled way, it will find all the character encodings. > It has to be called very early, before creating an interpreter. The results are stored in private variables that are used for all threads. > If it can not find the executable, no harm is done: it will have initialised the subsystems anyway. * The routine Tcl\_Init\(\) is responsible for setting up the script library by evaluating the script _init.tcl_. It should be called after the creation of an interpreter, to add the various commands to it. > If it can not find this script, it will return with an error. > \(The routine actually has two additional hooks to allow customisation, but these will probably be used in unusual circumstances only.\) The script _init.tcl_ and any it sources \(directly or indirectly via auto\_load\) must be found via the _tcl\_library_ variable. On UNIX this variable is initialised via the _TCL\_LIBRARY_ environment variable is used, whereas on MS Windows the pathname of the Tcl DLLs is used as well. As long as these scripts can be found, they can actually reside in a large number of directories with names related to the Tcl library path. This leads to the following code to create a full-fledged interpreter: Tcl_Interp * interp ; /* Initialise the Tcl library thouroughly */ Tcl_FindExecutable( argv[0] ) ; /* Create the interp, evaluate "init.tcl" for the script level initialisation. */ interp = Tcl_CreateInterp() ; if ( Tcl_Init( interp ) != TCL_OK ) { ... Report the error } With _init.tcl_ loaded, we have a number of additional commands and global variables: * tclLog, unknown, auto\_load, auto\_execok are the most important ones. * auto\_path, errorInfo, errorCode To create an interpreter that can handle Tk as well, you should be aware of the following: * Tk-able interpreters always need to be initialised via Tk\_Init\(\) and therefore require the start-up scripts: these scripts contain the default bindings and resource definitions and are therefore indispensable for Tk. * An application written using Tk needs to process events in a well-defined event loop. TODO: how to write the event loop, what choices are available? # Initialisation via the standard shell The details of the initialisation done in the standard tclsh shell are quite intricate. They involve, in addition to the initialisation via Tcl\_FindExecutable\(\) and Tcl\_Init\(\) also: * processing the command-line arguments * customisation via various hooks * preparing the Tcl parser by setting the locale to "C", as only this guarantees everything works as expected. A summary of the steps found in the initialisation code is given below: * main\(\) is a system-dependent routine which: > \* sets the locale \(Windows version\) > \* parses the command-line according to the UNIX rules \(Windows version\) > \* calls Tcl\_Main\(\), which is not supposed to return * Tcl\_Main\(\) takes as arguments the well-known _argc/argv_ command-line arguments and a pointer to the initialisation routine, which in the case of _tclsh_ is Tcl\_AppInit\(\): > \* After calling Tcl\_FindExecutable\(\), processing the command-line arguments and calling the initialisation routine, it can do either of two things: > > \* Evaluate the script file, if the first argument does not start with a minus sign > > \* Or go into an interactive loop to read the commands from the prompt. The preparation in that case is to evaluate the start-up script \(such as ~/.tclshrc or ~/tclshrc.tcl\) > \* It exits by evaluating the Tcl "exit" command, not by calling the C routine _exit\(\)_ directly * The standard initialisation routine Tcl\_AppInit\(\) is meant to initialise the various application-specific commands and static packages via routines like Tcl\_CreateCommand\(\). It also sets the Tcl variable "tcl\_rcFile" to the user's start-up script. > \(Curiously, the standard routine is found in a platform-dependent source file, tclXXXInit.c\) * Tcl\_Init\(\) by the way provides two hooks for customisation: > \* A pre-initialisation script that gets evaluated when the static variable "tclPreInitScript" has been set. > \* The initScript variable that defines a Tcl procedure that looks up the _init.tcl_ script. Thus, before the shell is ready for processing, a lot of initialisation is done. Much of this process can be customised without the need to change the standard source files. # Overview This section provides an overview of the resources that an application requires, given the type of usage: _Bare Tcl only interpreter:_ * Just the Tcl dynamic libraries _Complete initialisation for Tcl only:_ * The Tcl dynamic libraries * The environment variable TCL\_LIBRARY * The initialisation script file _init.tcl_ * The character encoding tables \(optional\) _Customised Tcl shell \(adapted Tcl\_AppInit\(\)\):_ * The Tcl dynamic libraries * The environment variable TCL\_LIBRARY * The initialisation script file _init.tcl_ * The character encoding tables \(optional\) * Possibly a so-called RC file to define the initialisation for interactive use _Customised Tk shell \(wish; adapted Tk\_AppInit\(\)\):_ * The Tcl and Tk dynamic libraries * The environment variables TCL\_LIBRARY and TK\_LIBRARY * The initialisation script file _init.tcl_, and the Tk specific bindings \(in _tk.tcl_ and others\) * The character encoding tables \(optional\) * Possibly a so-called RC file to define the initialisation for interactive use Equally important are the limitations: _Bare Tcl only interpreter:_ * No customisable initialisation \(not automatically\) * No access to the command-line arguments or the directory that contains the executable * No alternative character encodings * Possibly problems loading packages, as the auxiliary procedures for this are defined in _init.tcl_ and others. * Possibly problems with the locale \(best to explicitly set it to "C"\) * No interactive use _Complete initialisation for Tcl only:_ * Possibly problems with the locale \(best to explicitly set it to "C"\) * No interactive use _Customised Tcl shell \(adapted Tcl\_AppInit\(\)\):_ * None _Customised Tk shell \(wish; adapted Tk\_AppInit\(\)\):_ * None ---- # Compiling and linking Nowadays, it seems the default to use dynamic or shared libraries. So, with many installations, there will exist dynamic versions of the libraries and sometimes there will be no static versions. This has a number of advantages: * The executables are much smaller, the memory usage can be smaller as well, as the code will be shared. * The libraries can be replaced without the need to rebuild the application. This is especially true if you enable the use of _stubs_ for your binary packages \(see below\). However, as the Tcl libraries now reside outside your application, they will have to be shipped with the application and the dynamic loader must somehow be able to find the libraries. The latter certainly has consequences: each system tends to have its own method. When you have the Tcl/Tk sources, you can decide to create your own libraries. Of special interest are the following two situations: * You want to be able to use the _stubs_ facility, as this makes it possible to run with different versions of Tcl/Tk with the same binary. * You want to get rid of as much extra stuff outside your application as possible, so you want to use the static version of the Tcl libraries. _Stubs_ were introduced to make binary extensions and applications independent of the specific Tcl version. They are enabled by defining the macro _TCL\_USE\_STUBS_ during the compilation and linking of the Tcl/Tk library and especially your own extension. In the initialisation procedure for your pacakge or application you need to initialise the stubs jump table via _Tcl\_InitStubs\(\)_: #ifdef USE_TCL_STUBS if (Tcl_InitStubs(interp, "8.1", 0) == NULL) { return TCL_ERROR; } #endif \(details: <http://mini.net/tcl/1687.html> \) The technique, as Brent Welch explains, is simple in principle: > By enabling stubs, all calls to Tcl routines are turned into function pointers. These pointers are kept in a large table that is filled with the correct pointer values via the Tcl\_InitStubs\(\) routine. Linking your application or extension should then be done against the "stub version" of the Tcl/Tk libraries. If you do not want dynamic libraries, then perhaps a build with the option _STATIC\_BUILD_ is a solution. With this option, static libraries are built. The libraries are then incorporated into the executable itself. _Note:_ On some platforms, notably Windows, the specific calling convention is then turned to standard C \(with dynamic libraries, the calling convention exports the various routines explicitly\). When you do not care about the dynamic libraries having to be present, at least be aware of the way the various systems want to define their position. The information above is summarised as follows: _Using dynamic libraries:_ * Most UNIX versions and LINUX use the environment variable LD\_LIBRARY\_PATH, colon-separated just like _PATH_ to indicate the position of dynamic libraries. * Some use the variable SHLIB\_PATH instead \(notably: HPUX\). * Under Windows \(all flavours\) the PATH variable is used and a predefined sequence of directories to find the DLL's. One important case is that the libraries are found in the same directory as the executable. _Building for general Tcl versions:_ * Compile your sources with the macro _TCL\_USE\_STUBS_ * Use the proper call to Tcl\_InitStubs\(\) to initialise the jump table. * Link against the stub versions of the Tcl/Tk libraries. _Building statically:_ * Use the flag STATIC\_BUILD to build the static Tcl/Tk libraries. * Use this flag for your own sources as well * Link against the static versions. # Copyright This document is placed in the public domain. |
Name change from tip/67.tip to tip/67.md.
|
| < | < | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | < > | | | | < > | < > | | | | | | | | | | < > | | | < > | | < > | | | | | | | | | | | | < > | | | | | < < < > > > | | | | | | < < > > | | | | | | | | < > | | < | > | | > | 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 | # TIP 67: Allow Subclassing of tk_getOpenFile, tk_getSaveFile on UNIX Author: Chris Nelson <[email protected]> Author: Al Zielaskowski <[email protected]> State: Withdrawn Type: Project Tcl-Version: 8.5 Vote: Pending Created: 09-Oct-2001 Post-History: ----- # Abstract On Microsoft Windows it is possible to "subclass" a standard dialog and add controls to it. This TIP proposes adding that feature to the _tk\_getOpenFile_ and _tk\_getSaveFile_ dialogs for non-Windows systems \(wherever _tkfbox.tcl_ and _xmfbox.tcl_ are used for these dialogs\). # Rationale In our work with Tk, we have need to save files in various formats and give the user control over more than just the file name when saving. While it is possible to have two separate dialogs - one for specifying the file name and location and another for other attributes - this is unwieldy and not very user friendly: all the related information should be in one dialog On Microsoft Windows, it is possible to add controls to standard dialogs \(indeed any window\) via "subclassing" \(cf <http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/commdlg\_4qlv.asp\).> \(This requires C programming but it is, at least, possible.\) On UNIX, no generic technique like subclassing exists. Even if we wished to invade the "standard dialog," - learning about the window's organization, adding widgets here and there - calling _tk\_getSaveFile_ blocks the caller and then returns a value after the dialog is destroyed so we have no opportunity to manipulate the dialog. To work around this, we need to have _tk\_getSaveFile_ call back into user code to add controls when the dialog is built. # Specification We add a _-subclass_ option to _tk\_getSaveFile_ and _tk\_getOpenFile_ \(on UNIX only\). The value of the _-subclass_ option is a Tcl command to evaluate to fill an extra frame near the bottom of the dialog. When the dialog is constructed, the subclass command, if any, is evaluated with the path to the frame appended as an additional argument. The subclass command can then fill the frame as needed. No additional semantic changes are needed for these additional controls to communicate with the program as such communication can be done through side effects. For example, user interaction with a checkbox created by the subclass command can be detected after the _tk\_getSaveFile_ dialog is closed by examining the value of the checkbox's global variable. # Reference Implementation This proposal has been implemented by Al Zielaskowski. A patch relative to Tk 8.4a3 follows: Index: tkfbox.tcl =================================================================== RCS file: /pti/prod/mrd/CvsRepository/tcl/tk/library/tkfbox.tcl,v retrieving revision 1.1.1.1 diff -u -w -r1.1.1.1 tkfbox.tcl --- tkfbox.tcl 2001/09/04 23:51:12 1.1.1.1 +++ tkfbox.tcl 2001/10/09 19:47:50 @@ -898,6 +898,7 @@ {-initialfile "" "" ""} {-parent "" "" "."} {-title "" "" ""} + {-subclass "" "" ""} } # The "-multiple" option is only available for the "open" file dialog. @@ -1087,9 +1088,22 @@ # Pack all the frames together. We are done with widget construction. # pack $f1 -side top -fill x -pady 4 + + # + # Add the user's subclass frame if one was specified + # + if {[string length $data(-subclass)]} { + frame $w.subclass -bd 0 + pack $w.subclass -side bottom -fill x \ + -padx [list [expr [winfo reqwidth $data(typeMenuLab)] + 8] \ + [expr [winfo reqwidth $data(okBtn)] + 8]] + eval $data(-subclass) $w.subclass + } + pack $f3 -side bottom -fill x pack $f2 -side bottom -fill x pack $data(icons) -expand yes -fill both -padx 4 -pady 1 + # Set up the event handlers that are common to Directory and File Dialogs # Index: xmfbox.tcl =================================================================== RCS file: /pti/prod/mrd/CvsRepository/tcl/tk/library/xmfbox.tcl,v retrieving revision 1.1.1.1 diff -u -w -r1.1.1.1 xmfbox.tcl --- xmfbox.tcl 2001/09/04 23:51:12 1.1.1.1 +++ xmfbox.tcl 2001/10/09 19:05:57 @@ -216,6 +216,7 @@ {-initialfile "" "" ""} {-parent "" "" "."} {-title "" "" ""} + {-subclass "" "" ""} } if { [string equal $type "open"] } { lappend specs {-multiple "" "" "0"} @@ -277,6 +278,7 @@ if {![winfo exists $data(-parent)]} { error "bad window path name \"$data(-parent)\"" } + } # ::tk::MotifFDialog_BuildUI -- @@ -360,6 +362,17 @@ pack $bot.ok $bot.filter $bot.cancel -padx 10 -pady 10 -expand yes \ -side left + + + # + # Add the user's subclass frame if one was specified + # + if {[string length $data(-subclass)]} { + frame $f3.subclass -bd 0 + pack $f3.subclass -side bottom -fill x -padx 4 -pady 4 + eval $data(-subclass) $f3.subclass + } + # Create the bindings: # # Notice of Withdrawal This TIP was Withdrawn by the TIP Editor following discussion on the tcl-core mailing list. The following is a summary of reasons for withdrawal: > This would make porting code between platforms obscenely difficult as there is no way for the subclassing to work the same way on all platforms. Better for people to roll their own, perhaps starting from the foundations of the UNIX file browsing code if they wish. # Copyright This document has been placed in the public domain. |
Name change from tip/68.tip to tip/68.md.
|
| < | < | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 68: Dynamic Trace Result Handling Author: Donal K. Fellows <[email protected]> State: Final Type: Project Tcl-Version: 8.4 Vote: Done Created: 16-Oct-2001 Post-History: ----- # Abstract This TIP proposes an extension to the _Tcl\_TraceVar_ API to cope with dynamically allocated results. # Rationale The current API for handling errors during variable accesses is based on static strings, which is perfectly adequate for the errors that Tcl generates of its own accord, but which is substantially at odds with the setting of traces on variables which may produce errors. The problem is that as those errors come from a Tcl script, they are allocated dynamically and fail to satisfy the static allocation rule mentioned previously. Normally this does not cause a problem, but under some circumstances \(as set out in Bug \#219393 <http://sf.net/tracker/?func=detail&aid=219393&group\_id=10894&atid=110894\)> it is possible for this to cause a memory fault or even memory corruption. This is because it can sometimes happen that the pointer to the supposedly static string winds up dangling as the string it was pointing to gets deleted out from underneath it \(the storage area used to static-ify the string is part of the trace structure, but the trace is permitted to delete that structure...\) Obviously this is not desirable! There are several possible fixes, but the two main ones are to: 1. use the _Tcl\_Preserve_ mechanism to postpone deletion of the allocated memory block until it has been copied into something more permanent. 2. add special handling so as to mark the error result coming back from the trace mechanism as something other than a static string. The main alternatives here are: > \* A dynamically-allocated C string, to be disposed of with _ckfree_. > \* A dynamically-allocated _Tcl\_Obj_ reference, to be disposed of with a single call to _Tcl\_DecrRefCount_. Although option 1 is the easiest to implement, it has the disadvantage of putting a new _non-obvious_ requirement on all variable traces, and that is that their results are all _Tcl\_Preserve_d before the end of the trace. This is feasible for the Tcl core, but unreasonable to ask of extension writers. Instead I prefer option 2, and it is possible to introduce this change in such a way that existing software does not see an API change \(i.e. there are no serious backward-compatibility issues\) and both styles of result listed above are supported. The advantage of supporting both of these is that dynamically allocated strings are a very easy interface for extension writers to use though not particularly efficient, and objects are a very efficient interface well-suited to the core itself but are not as easy to use. \(It is far easier to adapt existing code to use dynamic strings as no understanding of lifespan management is required.\) # Changes To achieve this, the following new flags will be defined: #define TCL_TRACE_RESULT_DYNAMIC 0x2000 #define TCL_TRACE_RESULT_OBJECT 0x4000 These flags, when passed to the _flags_ argument of _Tcl\_TraceVar_ \(and related functions\) alter the interpretation of the value returned by the call to the _proc_ parameter from the default behaviour \(a static string\) to be either a string to be deallocated by Tcl as and when it sees fit using _ckfree_ \(when _TCL\_TRACE\_RESULT\_DYNAMIC_ is specified\) or to be a _Tcl\_Obj_ \(which must be cast to a _char *_ for type compatibility\) to be disposed of when the error message is no longer required \(when _TCL\_TRACE\_RESULT\_OBJECT_ is specified.\) It is an error to specify both flags on the same call. The core will then be modified to use this mechanism for variable traces as set up by the _trace_ command. # Copyright This TIP is placed in the public domain. # Reference For reference, the pre-TIP definition of the _Tcl\_TraceVar_ function is as follows: int Tcl_TraceVar(Tcl_Interp *interp, char *varName, int flags, Tcl_VarTraceProc *proc, ClientData clientData) \(There is a corresponding function that takes the variable name as a pair of strings.\) All parameters have the usual obvious interpretations, with the _flags_ being an OR-ed combination of the following flags: TCL\_TRACE\_READS: Invoke the callback when the variable is read. TCL\_TRACE\_WRITES: Invoke the callback when the variable is written. TCL\_TRACE\_UNSETS: Invoke the callback when the variable is unset. TCL\_TRACE\_ARRAY: Invoke the callback when the variable is accessed as an array. TCL\_GLOBAL\_ONLY: Force the lookup of the variable in the global scope, and not the current one. |
Name change from tip/69.tip to tip/69.md.
|
| < | < | | | | | | | | | | > | | | | | | | | | | | | | | | | | | | < > | | | | | | | < > | | | | | | | | | | | | | | | < < < > > > | | | | | | | | | | | | | | | | | | | | | | | | < > | | | | < > | | | | | | | | | | | | | | < > | | | < < > > | | | | | | | < > | | | < < > > | | | | | | | | | | | | < > | | < < < < | > > > > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | < > | | | | < > | | | | | | | | | | | | | | | | | | | | | | | > | 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 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 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 | # TIP 69: Improvements for the Tcl Hash Table Author: George A. Howlett <[email protected]> Author: Don Porter <[email protected]> Author: Donal K. Fellows <[email protected]> State: Draft Type: Project Vote: Pending Created: 16-Oct-2001 Post-History: Discussions-To: news:comp.lang.tcl Tcl-Version: 9.0 ----- # Abstract This document describes various improvements to the existing Tcl hash table. They include support for 64 bit platforms, better memory performance, and improved array hashing. The goal is a hash table that improves Tcl/Tk, but also can be used in industrial strength applications. # Introduction A strength of Tcl that has not diminished in the advance of other scripting languages \(Perl, Python, Ruby, etc.\) is the easy way its command language can be extended with C/C\+\+ code. For example, the prominence of Tcl in Electronic Design Automation \(EDA\) tools is striking. It's hard to find EDA tools that do not use Tcl to some degree. At the same time, there is a current trend toward 64-bit computing platforms. The impetus has been from industry \(like EDA\) rather than office or home users, wanting to solve bigger problems, faster. If Tcl applications are to operate on 64-bit platforms, a big first step towards this goal will be a 64-bit version of the Tcl hash table. The current Tcl hash table performs well on 32-bit platforms. It has been tuned and wrung out handling internal Tcl/Tk code. But its one word hash function #define RANDOM_INDEX(tablePtr, i) \ (((((long) (i))*1103515245) >> (tablePtr)->downShift) & (tablePtr)->mask) can not hash the longer 64-bit addresses properly. Example: Tcl_HashTable t; unsigned long i; char *base, *addr; int isNew; char *mesg; Tcl_InitHashTable(&t, TCL_ONE_WORD_KEYS); base = 0xFFFFFF000000000UL; for (i = 0; i < 100; i++) { addr = base + i * 0x100000000; hPtr = Tcl_CreateHashEntry(&t, addr, &isNew); } mesg = Tcl_HashStats(&t); fprintf(stderr, "Stats\n%s\n", mesg); free((char *)mesg; Note that the keys all have zeros in the lower 32 bits. All 100 entries will hash to the same value. Driving the need for 64-bit systems is the ability to address more memory. So it's imperative that Tcl hash table be able to hash large virtual addresses. Building upon the current hash table implementation, the following sections describe specific areas for improvement: * improved array/structure hashing * better memory performance * support for 64-bit platforms The goal is an improved Tcl hash table for internal Tcl and Tk code, but also high performance applications. # Improved Array/Structure Hashing The Tcl hash table handles three types of hash keys: string keys, one word keys, and multi-word keys. Each key type has its own hash function associated with it. The benefit of this approach is that better hash functions can be used for the specific types, than one general function for all types. The string and one word hash functions are very good for typical keys. The multi-word or array hash is not as good. The array hash sums the each word of the array and then randomizes the result. for (index = 0, count = tablePtr->keyType, iPtr1 = arrayPtr; count > 0; count--, iPtr1++) { index += *iPtr1; } index = RANDOM_INDEX(tablePtr, index); This works poorly for many types of hash keys. For an contrived example of hashing 1 million 3D coordinates, typedef struct { double x, y, z; } Double3; double d3; Tcl_InitHashTable(&t, sizeof(Double3) / sizeof(int)); for (i = 0; i < 100; i++) { for (j = 0; j < 100; j++) { for (k = 0; k < 100; k++) { d3.x = (double)i; d3.y = (double)j; d3.z = (double)k; hPtr = Tcl_CreateHashEntry(&t, (char *)&d3, &isNew); } } } we get a hash table with an average search distance of 1082.3. The maximum distance is 3324! Replacing the hash function with Bob Jenkins' <http://burtleburtle.net/bob> 32-bit mixing function #define MIX32(a,b,c) \ a -= b, a -= c, a ^= (c >> 13), \ b -= c, b -= a, b ^= (a << 8), \ c -= a, c -= b, c ^= (b >> 13), \ a -= b, a -= c, a ^= (c >> 12), \ b -= c, b -= a, b ^= (a << 16), \ c -= a, c -= b, c ^= (b >> 5), \ a -= b, a -= c, a ^= (c >> 3), \ b -= c, b -= a, b ^= (a << 10), \ c -= a, c -= b, c ^= (b >> 15) int a, b, c, len; len = length; a = b = GOLDEN_RATIO32; /* An arbitrary value */ c = 0; /* Previous hash value */ while (len >= 3) { /* Handle most of the key */ a += key[0]; b += key[1]; c += key[2]; MIX32(a, b, c); key += 3; len -= 3; } c += length; switch(len) { case 2 : b += key[1]; case 1 : a += key[0]; } MIX32(a, b, c); return c; yields a table with an average search distance of 1.48. The maximum distance is 8. The Jenkins' hash function provides good results for many different types of arrays and structures. The disadvantage is that the hash function is slightly more expensive to compute. # Improving RebuildTable. The cost of computing a hash function is especially felt each time table is rebuilt as new entries are added. The _RebuildTable_ function calls the hash function of each entry to recompute its new location in the bigger table. for (oldChainPtr = oldBuckets; oldSize > 0; oldSize--, oldChainPtr++) { for (hPtr = *oldChainPtr; hPtr != NULL; hPtr = *oldChainPtr) { *oldChainPtr = hPtr->nextPtr; if (tablePtr->keyType == TCL_STRING_KEYS) { index = HashString(hPtr->key.string) & tablePtr->mask; } else if (tablePtr->keyType == TCL_ONE_WORD_KEYS) { index = RANDOM_INDEX(tablePtr, hPtr->key.oneWordValue); } else { index = HashArray(hPtr->key.words, tablePtr->keyType) & tablePtr->mask; } hPtr->bucketPtr = &(tablePtr->buckets[index]); hPtr->nextPtr = *hPtr->bucketPtr; *hPtr->bucketPtr = hPtr; } } The new bucket location is then stored in the hash entry. Except for one word keys, the hash value is invariant of the table size. If the hash value was stored with each entry, then it would not need to be recomputed each time the table is rebuilt. for (oldChainPtr = oldBuckets; oldSize > 0; oldSize--, oldChainPtr++) { for (hPtr = *oldChainPtr; hPtr != NULL; hPtr = *oldChainPtr) { *oldChainPtr = hPtr->nextPtr; if (tablePtr->keyType == TCL_ONE_WORD_KEYS) { index = RANDOM_INDEX(tablePtr, hPtr->key.oneWordValue); } else { index = hPtr->hval & tablePtr->mask; } hPtr->bucketPtr = &(tablePtr->buckets[index]); hPtr->nextPtr = *hPtr->bucketPtr; *hPtr->bucketPtr = hPtr; } } This would increase size of an hash entry, except that the pointer to the hash bucket is now redundant, since it can cheaply be computed. bucketPtr = tablePtr->buckets + (hPtr->hval & tablePtr->mask); An added benefit is that hash table lookups become faster and easier to perform. If there is more than one hash entry in a bucket, you don't need to examine the key unless the entry has the same hash value. for (hPtr = tablePtr->buckets[hindex]; hPtr != NULL; hPtr = hPtr->nextPtr) { /* Don't look at entry unless the hash value is the same. */ if (hPtr->hval == hval) { register int *iPtr1, *iPtr2; int count; for (iPtr1 = arrayPtr, iPtr2 = (int *)hPtr->key.words, count = tablePtr->keyType; ; count--, iPtr1++, iPtr2++) { if (count == 0) { return hPtr; } if (*iPtr1 != *iPtr2) { break; } } } } _Don Porter <[email protected]>_ > _It appears that the recommendations of this section have already been implemented in Tcl 8.4. In particular, when the symbol TCL\_HASH\_KEY\_STORE\_HASH == 1 \(as it does by default\), then the hash value is stored in each entry instead of the bucketPtr._ > _If that is correct, then I recommend this section of the TIP be removed. If not, more detail about how this proposal differs from the 8.4 implementation, and an argument why the proposal is superior are in order._ # Better Memory Performance One enduring complaint of the Tcl hash table on comp.lang.tcl is its unexpected memory costs. A table of 1 million one word key entries uses over 36 Megabytes. A hash entry is 20 bytes long. typedef struct Tcl_HashEntry { struct Tcl_HashEntry *nextPtr; /* Pointer to next entry in this * hash bucket, or NULL for end of * chain. */ struct Tcl_HashTable *tablePtr; /* Pointer to table containing entry. */ struct Tcl_HashEntry **bucketPtr; /* Pointer to bucket that points to * first entry in this entry's chain: * used for deleting the entry. */ ClientData clientData; /* Application stores something here * with Tcl_SetHashValue. */ union { /* Key has one of these forms: */ char *oneWordValue; /* One-word value for key. */ int words[1]; /* Multiple integer words for key. * The actual size will be as large * as necessary for this table's * keys. */ char string[4]; /* String for key. The actual size * will be as large as needed to hold * the key. */ } key; /* MUST BE LAST FIELD IN RECORD!! */ } Tcl_HashEntry; Each entry stores a pointer to its hash table. This field is used only for deleting a hash entry. But if the hash table is passed to _Tcl\_DeleteHashEntry_, the hash entry can be reduced to 16 bytes. Inspecting Tcl/Tk code, I could not find a case where the hash table was not easily available to pass as a parameter. Each hash entry is allocated using _malloc_. System memory allocators typically add 8-16 bytes overhead for each allocation. Worse, calls to _malloc_ and _free_ tend to dominate the cost of large hash tables. _Tcl\_DeleteHashTable_ becomes very slow, freeing hash entries scattered across pages of virtual memory. For large hash tables, a pool allocation scheme can improve both reduce the amount of memory used and improve memory performance. By allocating memory in larger chunks, the number of _malloc_ and _free_ calls is dramatically reduced. Fixed size allocators \(one word keys and array keys\) can also reclaim and reuse memory from deleted entries. The disadvantage of pool allocation is that memory is not released until the hash table is deleted. This is less of an issue for large tables which tend to grow to a steady-state size. Both Tcl and Tk use hash tables to keep track of small amounts of information that probably don't pool allocation. So to retain compatibility, a new specialized initialization routine can be used to indicate when to use pool-based allocation. Tcl_InitHashTableWithPool(&table, TCL_ONE_WORD_KEYS); The standard _Tcl\_InitHashTable_ call Tcl_InitHashTable(&table, TCL_ONE_WORD_KEYS); will still use _malloc_ and _free_. # Support for 64-bit Platforms. While the C language makes no guarantees of a type's size or its relation to other types, current programming practice assumes that integers, longs, and pointers are all 32 bits long. This, of course, changes with 64-bit systems where pointers are 64-bits wide. Depending upon the programming model, longs and ints may or may not be 64 bits too. Datatype LP64 ILP64 LLP64 ILP32 LP32 char 8 8 8 8 8 short 16 16 16 16 16 _int32 32 int 32 64 32 32 16 long 64 64 32 32 32 long long 64 pointer 64 64 64 32 32 ILP32 is typical for 32 bit systems. Windows 3.1 was a LP32 model. In the LP64 model, pointers and longs are 64 bits, but ints remain 32 bits wide. The LLP model retains the 32-bits for ints and longs, but adds a 64-bit "long long" type. Most 64-bit Unix systems \(Solaris, HP-UX, Tru64, AIX\) are LP64. I believe that Win64 is LLP. The first problem is that addresses are now 64-bits, not 32. This means that existing code such as Tcl_InitHashTable(&table, TCL_ONE_WORD_KEYS); ptr = CreateSomeObject(); hPtr = Tcl_CreateHashEntry(&table, (void *)ptr, &isNew); can possibly fail because the 32-bit one word hash function can't properly hash the 64-bit pointer address. _Don Porter <[email protected]>_ > _Pardon the interruption, but I do not understand what is meant by the assertion that hashing of 64-bit pointers "can possibly fail". I've used Tcl on a 64-bit Alpha system for years, hashing 64-bit pointers the whole time. What failures should I be seeing?_ #define RANDOM_INDEX(tablePtr, i) \ (((((long) (i))*1103515245) >> (tablePtr)->downShift) & (tablePtr)->mask) The above one word hash function can be replaced with a 64-bit version of Donald Knuth's multiplicative hash function. ((key * GOLDEN_RATIO64) >> downShift) & tablePtr->mask) where downShift is 64 - log2\(tableSize\) and the GOLDEN\_RATION64 is a prime approximately equal to \(sqrt\(64\) - 1\) / 2. The 64-bit array function is again from Bob Jenkins. This time it's a 64-bit mixing function. #define MIX64(a,b,c) \ a -= b, a -= c, a ^= (c >> 43), \ b -= c, b -= a, b ^= (a << 9), \ c -= a, c -= b, c ^= (b >> 8), \ a -= b, a -= c, a ^= (c >> 38), \ b -= c, b -= a, b ^= (a << 23), \ c -= a, c -= b, c ^= (b >> 5), \ a -= b, a -= c, a ^= (c >> 35), \ b -= c, b -= a, b ^= (a << 49), \ c -= a, c -= b, c ^= (b >> 11), \ a -= b, a -= c, a ^= (c >> 12), \ b -= c, b -= a, b ^= (a << 18), \ c -= a, c -= b, c ^= (b >> 22) uint64_t a, b, c, len; len = length; a = b = GOLDEN_RATIO64; /* An arbitrary value */ c = 0; /* Previous hash value */ while (len >= 3) { /* Handle most of the key */ a += key[0]; b += key[1]; c += key[2]; MIX64(a,b,c); key += 3; len -= 3; } c += length; switch(len) { case 2 : b += key[1]; case 1 : a += key[0]; } MIX64(a,b,c); return c; Note that it also takes advantage of the 64-bit word size. # Summary The following improvements to the current Tcl hash table have been suggested. * Replace the current array hash function. * Replace the bucket pointer in the hash entry with its hash value. This allows the table to be rebuilt without rehashing each entry. It also speeds bucket searches. * Remove the tablePtr from the hash entry, a 20% savings. This requires that callers of _Tcl\_DeleteHashEntry_ pass the hash table as a parameter. * Allow the hash table to use fixed or variable size pool allocation since _malloc_ and _free_ costs dominate large tables. Pool allocation substantial speeds large tables while also saving 8-16 bytes per entry. This can be done while still providing the normal _malloc_/_free_ versions. * Support 64-bit platforms. This requires 64-bit versions of one word and array hash functions. The suggested changes are nothing new and can be found in most hash table implementations. This work builds on the already solid foundation of the current hash table. With the above improvements, the Tcl hash table can be used in high performance applications. It also adds a useful piece to the 64-bit Tcl/Tk port. I've created and tested a new hash table implementation under the following systems. System 32 64 linux-ix86-gcc x Solaris-v9-cc x x Solaris-v9-gcc x x HPUX-11-cc x x HPUX-11-gcc x Win2k x It will be made publicly available on SourceForge. # Hashing of Malicious Strings _Donal K. Fellows adds:_ In 2003 a possible denial-of-service attack on hash tables was published that operated by making a majority of keys map to the same bucket. While this would not make the hashes function incorrectly - there would be no extra memory consumed or incorrect accesses to memory - it still permits an attacker to escalate the cost of hash accesses from O\(1\) to O\(n\) in the normal case \(and with obvious knock-on effects for the order of other algorithms\) and so mount an attack out-of-scale with the effort required to set the attack up. The way to fix this is to use a different hashing function for string hashing that varies the exact hashing algorithm on a table-by-table basis, and to base that algorithm on a hashing function with better spectral properties than Tcl's current \(extremely simple\) one. An algorithm that might be suitable for such uses is described online <http://burtleburtle.net/bob/hash/evahash.html> though the code would need substantial adaption \(including the addition of a fairly strong random number generator\) before being placed in the core. # Copyright This document has been placed in the public domain. |
Name change from tip/7.tip to tip/7.md.
|
| < | < | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | < > | | | < > | | | < > | | | | | | | | | | | | | | < > | < > | | | < > | | | | | | | | | < > | | | < > | | | | | | | < > | | | | | | | | | | | | < < > > | | | | | | | | | | | | | | | | | | | | | | | | < > | | | | | | | | < > | | | | | | | | | | | | | | | | | | | | | | | | | < > | | | | | | | | | | | | | | | | | < > | | | | < > | | | | | | | < > | | | | | | | | < > | < < < < < < < < < < < < > > > > > > > > > > > > | < > | | < > | | > > > < < < < > | < > | | < > | | < > | | < > | | | | < > | | | | | | | | < > | | | < > | | | | < > | | | | | | | < > | < > | | | < > | < > | | | | | < > | < > | | | | | | | | < > | < > | | | | | < > | | | < > | | | | | | < > | < > | | | | | < > | | | | < > | | < > | | | < > < > | | | | | < > | | < > | | | | < > | | | | | | | | < > | | | | | | < > | | | | | < > | | | | | < < > > | | | < > | | | | < > | | | | | < > | | | | | | | | | | | | | | | | < > | | | | | < > | | | | < > | | | | | | | | | | | | | | | | | | | < > | < > | | | | < > | | < > | | | < > | | | < > | | < > | < > | | | | | | | | | < > | < < > > | < > | < > | | | | < > | | | | | < > | | | < > | | | | | | | | | | | | | | | | | | | | | | | | | | < > | | > > > > < < < < < > | | | | | < > | < > | | < > | | | | < > | < > | < > | < > | | < > | | < > | | | | | | | | | | | | | | | | | | | < > | | > > > > > > > > > > > > > < < < < < < < < < < < < < < > | | | < > | | < > | | | < > | < > | | < > | < > | | > < < > | | | | < > | < > | | | | | < > | | | | | < > | | | | < > | | | | | | | < > | | | | | < > | | < > | | | < > | | | | < > | | < > | | | | | | | | | < > | | < > | < > | | | | | < > | | < > | | | < > | | | | | | < > | < < > > | | | | | | | | | | | < > | | | | | | | | | | | | | | | | | | | | | < > | | | > | 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 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 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 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 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 | # TIP 7: Increased resolution for TclpGetTime on Windows Author: Kevin Kenny <[email protected]> State: Final Type: Project Vote: Done Created: 26-Oct-2000 Tcl-Version: 8.4 Discussions-To: news:comp.lang.tcl Post-History: ----- # Abstract Tcl users on the Windows platform have long been at a disadvantage in attempting to do code timing studies, owing to the poor resolution of the Windows system clock. The _time_ command, the _clock clicks_ command, and all related functions are limited to a resolution of \(typically\) 10 milliseconds. This proposal offers a solution based on the Windows performance counter. It presents a means of disciplining this counter to the system clock so that _TclpGetTime_ \(the underlying call that the above commands use\) can return times to microsecond precision with accuracy in the tens of microseconds. # Change history _2 November 2000:_ Modified the TIP to discuss the issues surrounding the fact that some multiprocessor kernels on Windows NT use the CPU timestamp counter as a performance counter. Modified the proposed patch to test for the two frequencies in common use on 8254-compatible real-time clocks, and enable using the performance counter only if its frequency matches one of them. Included the proposed patch inline for review rather than as a pointer off to dejanews. # Rationale The Windows implementation of _TclpGetTime_, as of Tcl 8.3.2, uses the _ftime_ call in the C library to extract the current system clock in seconds and milliseconds. While this time value has millisecond precision, its actual resolution is limited by the tick rate of the Windows system clock, normally 100 Hz. Similarly, _TclpGetClicks_ uses the _GetTickCount_ function of _kernel32.dll_ to get the number of milliseconds since bootload; once again, the actual resolution of this call is limited to the tick rate of the system clock. The Windows Platform APIs offer several timers of different accuracy. The most precise of these is _QueryPerformanceCounter_, which operates at an unspecified frequency \(returned by _QueryPerformanceFrequency_\) that is typically about 1.19 MHz. <http://support.microsoft.com/support/kb/articles/Q172/3/38.asp> has details of the call, with sample code. The documentation for Windows suggests that this function is available only on certain versions of the operating system; in fact, it is implemented in every extant version of Win32 with the exception of Win32s and Windows CE 1.0. Since Visual C\+\+ 6, on which the Tcl distribution depends, will no longer compile code for those two platforms, I assert that they may be safely ignored. The documentation for Windows also states that _QueryPerformanceCounter_ is available only on certain hardware. In practice, this is not an issue; I have never encountered a Windows implementation on an x86 platform that lacks it, and Alpha has it as well. In any case, the reference implementation tests for the success or failure of the system calls in question, and falls back on the old way of getting time should they return an error indication. Users of any platform on which the performance counter is not supported should therefore be no worse off than they have ever been. A worse problem with the performance counter is that its frequency is poorly calibrated, and is frequently off by as much as 200 parts per million. Moreover, the frequency drifts over time, frequently having a sensitive dependency to temperatures inside the computer's case. This problem is not insurmountable. The fix is to maintain the observed frequency of the performance counter \(calibrated against the system clock\) as a variable at run time, and use that variable together with the value of the performance counter to derive Tcl's concept of the time. This technique is well known to electronic engineers as the "phase locked loop" and is used in network protocols such as NTP<http://www.eecis.udel.edu/~ntp/> . One problem that is apparently insurmountable is that certain multiprocessor systems have hardware abstraction layers that derive the performance counter from the CPU timestamp counter in place of a real-time clock reference. This implementation causes the performance counter on one CPU to drift with respect to the other over time; if a thread is moved from one processor to another, it cannot derive a meaningful result from comparing two successive values of the counter. Moreover, if the CPU clock uses a "gearshift" technique for power management \(as on Intel SpeedStep or Transmeta machines\), the CPU timestamp counter ticks at a non-constant rate. The proposed implementation addresses the problem by using the performance counter only if its nominal frequency is either 1.193182 MHz or 3.579545 MHz. These two frquencies are the common rates when 8254-compatible real-time clock chips are used; virtually all PCI bus controllers have such chips on board. This solution therefore adapts to the vast majority of workstation-class Windows boxes, and is virtually certain to exclude implementations derived from the CPU clock since no modern CPU is that slow. The patch has been tested on several desktop and laptop machines from Compaq, Dell, Gateway, HP, Micron, and Packard Bell, with processors ranging from a 50 MHz 486 to a 750 MHz Pentium III, including laptops using SpeedStep technology. It passes the clock-related test cases on all these platforms; it falls back to the old clocks with 10-ms precision on multiprocessor servers from Compaq and HP. \(Using the performance counter actually would have worked on the HP server, which apparently has some way of making sure that the results of _QueryPerformanceCounter_ are consistent from one CPU to another. The performance counter on the Compaq machine was observed to be inconsistent between the two CPU's.\) # Specification This document proposes the following changes to the Tcl core: 1. \(tclWinTime.c\) Add to the static data a set of variables that manage the phase-locked techniques, including a _CRITICAL\_SECTION_ to guard them so that multi-threaded code is stable. 2. \(tclWinTime.c\) Modify _TclpGetSeconds_ to call _TclpGetTime_ and return the 'seconds' portion of the result. This change is necessary to make sure that the two times are consistent near the rollover from one second to another. 3. \(tclWinTime.c\) Modify _TclpGetClicks_ to use TclpGetTime to determine the click count as a number of microseconds. 4. \(tclWinTime.c\) Modify _TclpGetTime_ to return the time as M\*Q\+B, where Q is the result of _QueryPerformanceCounter_, and M and B are variables maintained by the phase-locked loop to keep the result as close as possible to the system clock. The _TclpGetTime_ call will also launch the phase-lock management in a separate thread the first time that it is invoked. If the performance counter is unavailable, or if its frequency is not one of the two common 8254-compatible rates, then _TclpGetTime_ will return the result of _ftime_ as it does in Tcl 8.3.2. 5. \(tclWinTime.c\) Add the clock calibration procedure. The calibration is somewhat complex; to save space, the reader is referred to the reference implementation for the details of how the time base and frequency are maintained. 6. \(tclWinNotify.c\) Modify _Tcl\_Sleep_ to test that the process has, in fact, slept for the requisite time by calling _TclpGetTime_ and comparing with the desired time. Otherwise, roundoff errors may cause the process to awaken early. 7. \(tclWinTest.c\) Add a _testwinclock_ command. This command returns a four element list comprising the seconds and microseconds portions of the system clock and the seconds and microseconds portions of the Tcl clock. 8. \(winTime.test\) Add to the test suite a test that makes sure that the Tcl clock stays within 1.1 ms of the system clock over the duration of the test. # Reference implementation This change was submitted as a patch to the old bug-tracking system at Scriptics <http://www.deja.com/getdoc.xp?AN=666545441&fmt=text> . It is being recycled as a TIP now that the Tcl Core Team is in place, since the process for advancing the old patches to the Core is not well defined. The link above should not be used to retrieve the current version of the patch, which appears below as an Appendix. Tests on several Wintel boxes have shown that the initial startup transient is less than about 10 seconds \(during which time the Tcl clock may be running 500 ppm fast or slow to bring it into step\); following this period, the motion of the Tcl clock is highly repeatable and uniform. If the system clock changes by more than 1 second during a run, as when the operator sets it using the eyeball-and-wristwatch method, the method of adjusting the performance frequency to preserve monotonicity and accuracy of interval measurements is hopeless. This is the only case where the Tcl clock is allowed to jump. The startup of the calibration loop does not introduce new instabilities in the behavior of [clock clocks] or _TclpGetTime_. [clock clicks] and other times that derive from _TclpGetTime_ also ought to be reliable from the beginning - assuming that _QueryPerformanceFrequency_ actually matches the crystal. The worst case while the initial calibration is going on ought to be that the Tcl clock runs 0.1% fast or slow. The point of the calibration loop is to correct for long-term drift. The problem, otherwise, is that _QueryPerformanceFrequency_ may be off by some tens of parts per million with respect to the system clock. Over a period of days, that would cause the Tcl clock to veer off from the system clock. For instance, once my machine is warmed up \(temperature is significant, believe it or not\), _QueryPerformanceFrequency_ is consistently 0.99985 of the correct value; without calibration, the performance-counter-derived clock drifts 13 seconds per day. The _capture transient_ of the calibration loop is a little different every time, but the one shown below is typical. The Tcl time starts out 2 ms fast with respect to the system time, and the initial estimate of performance frequency is off, too. At 2 seconds in, the calibration loop takes over and makes the clock run 0.1% slow to bring it in line; by 5 seconds in, it's lined up. There's some phase noise over the next 40 seconds or so, by which time the performance frequency is locked on quite closely. The outliers above the line represent the fact that [after] events sometimes arrive late because of various other things going on in Windows. ![Typical capture transient](../assets/7capture.gif) The script that gathered the raw data plotted above appears below. foreach { syssecs sysusec tclsecs tclusec } [testwinclock] {} set basesecs $syssecs set baseusec $sysusec set nTrials 10000 for { set i 0 } { $i < $nTrials } { incr i } { set values {} for { set j 0 } { $j < 5 } { incr j } { foreach { syssecs sysusec tclsecs tclusec } [testwinclock] {} set systime [expr { ($syssecs - $basesecs) + 1.0e-6 * $sysusec - 1.0e-6 * $baseusec }] set tcltime [expr { ($tclsecs - $basesecs) + 1.0e-6 * $tclusec - 1.0e-6 * $baseusec }] set timediff [expr { $tcltime - $systime }] lappend values [list $systime $timediff $tcltime] after 1 } foreach { elapsed timediff tcltime } \ [lindex [lsort -real -index 1 $values] 0] {} lappend history $elapsed $timediff $tcltime } set f [open ~/test2.dat w] foreach { elapsed timediff tcltime} $history { puts $f "$elapsed\t$timediff\t$tcltime" } close $f To quantify how reproducible the measurements are, I threw a patched tclsh the torture test of executing [time {}] ten million times, and made a histogram of the results. The figure below shows the results. The dots represent individual sample bins, and the solid line is the cumulative count of samples. The vast majority of samples show either five or six microseconds. 99.9% take fewer than nine. There are many samples that take longer, owing to either servicing interrupts or losing the processor to other processes. The lines at 21, 31 and 42 microseconds show up in repeated runs on my machine; I suspect that they represent time spent servicing different sorts of video interrupts. It's less clear to me what the other outliers might be; Windows has a tremendous amount of stuff going on even when it's apparently idle. ![Histogram of results of {[time} {{}].}](../assets/7histogram.gif) All tests in the test suite continue to pass with the patch applied. # Notes If you care about time to the absolute precision that this change can achieve, it is of course necessary to discipline the Windows system clock as well. Perhaps the best way is to use one of the available NTP packages \(<http://www.eecis.udel.edu/~ntp/> for further information\). # Copyright This document has been placed in the public domain. # Appendix The proposed set of patches to the Tcl 8.3.2 code base appears here. *** ../tcl8.3.2base/src/tcl8.3.2/win/tclWinNotify.c Fri Jul 2 18:08:30 1999 --- ./src/tcl8.3.2/win/tclWinNotify.c Thu Aug 24 23:29:12 2000 *************** *** 510,514 **** Tcl_Sleep(ms) int ms; /* Number of milliseconds to sleep. */ { ! Sleep(ms); } --- 510,548 ---- Tcl_Sleep(ms) int ms; /* Number of milliseconds to sleep. */ { ! /* ! * Simply calling 'Sleep' for the requisite number of milliseconds ! * can make the process appear to wake up early because it isn't ! * synchronized with the CPU performance counter that is used in ! * tclWinTime.c. This behavior is probably benign, but messes ! * up some of the corner cases in the test suite. We get around ! * this problem by repeating the 'Sleep' call as many times ! * as necessary to make the clock advance by the requisite amount. ! */ ! ! Tcl_Time now; /* Current wall clock time */ ! Tcl_Time desired; /* Desired wakeup time */ ! int sleepTime = ms; /* Time to sleep */ ! ! TclpGetTime( &now ); ! desired.sec = now.sec + ( ms / 1000 ); ! desired.usec = now.usec + 1000 * ( ms % 1000 ); ! if ( desired.usec > 1000000 ) { ! ++desired.sec; ! desired.usec -= 1000000; ! } ! ! for ( ; ; ) { ! Sleep( sleepTime ); ! TclpGetTime( &now ); ! if ( now.sec > desired.sec ) { ! break; ! } else if ( ( now.sec == desired.sec ) ! && ( now.usec >= desired.usec ) ) { ! break; ! } ! sleepTime = ( ( 1000 * ( desired.sec - now.sec ) ) ! + ( ( desired.usec - now.usec ) / 1000 ) ); ! } ! } *** ../tcl8.3.2base/src/tcl8.3.2/win/tclWinTest.c Thu Oct 28 23:05:14 1999 --- ./src/tcl8.3.2/win/tclWinTest.c Mon Sep 4 22:45:56 2000 *************** *** 22,27 **** --- 22,31 ---- static int TestvolumetypeCmd _ANSI_ARGS_((ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); + static int TestwinclockCmd _ANSI_ARGS_(( ClientData dummy, + Tcl_Interp* interp, + int objc, + Tcl_Obj *CONST objv[] )); /* *---------------------------------------------------------------------- *************** *** 52,57 **** --- 56,63 ---- (ClientData) 0, (Tcl_CmdDeleteProc *) NULL); Tcl_CreateObjCommand(interp, "testvolumetype", TestvolumetypeCmd, (ClientData) 0, (Tcl_CmdDeleteProc *) NULL); + Tcl_CreateObjCommand(interp, "testwinclock", TestwinclockCmd, + (ClientData) 0, (Tcl_CmdDeleteProc *) NULL); return TCL_OK; } *************** *** 187,190 **** --- 193,267 ---- Tcl_SetResult(interp, volType, TCL_VOLATILE); return TCL_OK; #undef VOL_BUF_SIZE + } + + /* + *---------------------------------------------------------------------- + * + * TestclockCmd -- + * + * Command that returns the seconds and microseconds portions of + * the system clock and of the Tcl clock so that they can be + * compared to validate that the Tcl clock is staying in sync. + * + * Usage: + * testclock + * + * Parameters: + * None. + * + * Results: + * Returns a standard Tcl result comprising a four-element list: + * the seconds and microseconds portions of the system clock, + * and the seconds and microseconds portions of the Tcl clock. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + + static int + TestwinclockCmd( ClientData dummy, + /* Unused */ + Tcl_Interp* interp, + /* Tcl interpreter */ + int objc, + /* Argument count */ + Tcl_Obj *CONST objv[] ) + /* Argument vector */ + { + CONST static FILETIME posixEpoch = { 0xD53E8000, 0x019DB1DE }; + /* The Posix epoch, expressed as a + * Windows FILETIME */ + Tcl_Time tclTime; /* Tcl clock */ + FILETIME sysTime; /* System clock */ + Tcl_Obj* result; /* Result of the command */ + LARGE_INTEGER t1, t2; + + if ( objc != 1 ) { + Tcl_WrongNumArgs( interp, 1, objv, "" ); + return TCL_ERROR; + } + + TclpGetTime( &tclTime ); + GetSystemTimeAsFileTime( &sysTime ); + t1.LowPart = posixEpoch.dwLowDateTime; + t1.HighPart = posixEpoch.dwHighDateTime; + t2.LowPart = sysTime.dwLowDateTime; + t2.HighPart = sysTime.dwHighDateTime; + t2.QuadPart -= t1.QuadPart; + + result = Tcl_NewObj(); + Tcl_ListObjAppendElement + ( interp, result, Tcl_NewIntObj( (int) (t2.QuadPart / 10000000 ) ) ); + Tcl_ListObjAppendElement + ( interp, result, + Tcl_NewIntObj( (int) ( (t2.QuadPart / 10 ) % 1000000 ) ) ); + Tcl_ListObjAppendElement( interp, result, Tcl_NewIntObj( tclTime.sec ) ); + Tcl_ListObjAppendElement( interp, result, Tcl_NewIntObj( tclTime.usec ) ); + + Tcl_SetObjResult( interp, result ); + + return TCL_OK; } *** ../tcl8.3.2base/src/tcl8.3.2/win/tclWinTime.c Tue Nov 30 19:08:44 1999 --- ./src/tcl8.3.2/win/tclWinTime.c Thu Nov 2 14:25:56 2000 *************** *** 38,47 **** --- 38,114 ---- static Tcl_ThreadDataKey dataKey; /* + * Calibration interval for the high-resolution timer, in msec + */ + + static CONST unsigned long clockCalibrateWakeupInterval = 10000; + /* FIXME: 10 s -- should be about 10 min! */ + + /* + * Data for managing high-resolution timers. + */ + + typedef struct TimeInfo { + + CRITICAL_SECTION cs; /* Mutex guarding this structure */ + + int initialized; /* Flag == 1 if this structure is + * initialized. */ + + int perfCounterAvailable; /* Flag == 1 if the hardware has a + * performance counter */ + + HANDLE calibrationThread; /* Handle to the thread that keeps the + * virtual clock calibrated. */ + + HANDLE readyEvent; /* System event used to + * trigger the requesting thread + * when the clock calibration procedure + * is initialized for the first time */ + + /* + * The following values are used for calculating virtual time. + * Virtual time is always equal to: + * lastFileTime + (current perf counter - lastCounter) + * * 10000000 / curCounterFreq + * and lastFileTime and lastCounter are updated any time that + * virtual time is returned to a caller. + */ + + ULARGE_INTEGER lastFileTime; + LARGE_INTEGER lastCounter; + LARGE_INTEGER curCounterFreq; + + /* + * The next two values are used only in the calibration thread, to track + * the frequency of the performance counter. + */ + + LONGLONG lastPerfCounter; /* Performance counter the last time + * that UpdateClockEachSecond was called */ + LONGLONG lastSysTime; /* System clock at the last time + * that UpdateClockEachSecond was called */ + LONGLONG estPerfCounterFreq; + /* Current estimate of the counter frequency + * using the system clock as the standard */ + + } TimeInfo; + + static TimeInfo timeInfo = { + NULL, 0, 0, NULL, NULL, 0, 0, 0, 0, 0 + }; + + CONST static FILETIME posixEpoch = { 0xD53E8000, 0x019DB1DE }; + + /* * Declarations for functions defined later in this file. */ static struct tm * ComputeGMT _ANSI_ARGS_((const time_t *tp)); + + static DWORD WINAPI CalibrationThread _ANSI_ARGS_(( LPVOID arg )); + + static void UpdateTimeEachSecond _ANSI_ARGS_(( void )); /* *---------------------------------------------------------------------- *************** *** 63,69 **** unsigned long TclpGetSeconds() { ! return (unsigned long) time((time_t *) NULL); } /* --- 130,138 ---- unsigned long TclpGetSeconds() { ! Tcl_Time t; ! TclpGetTime( &t ); ! return t.sec; } /* *************** *** 89,95 **** unsigned long TclpGetClicks() { ! return GetTickCount(); } /* --- 158,175 ---- unsigned long TclpGetClicks() { ! /* ! * Use the TclpGetTime abstraction to get the time in microseconds, ! * as nearly as we can, and return it. ! */ ! ! Tcl_Time now; /* Current Tcl time */ ! unsigned long retval; /* Value to return */ ! ! TclpGetTime( &now ); ! retval = ( now.sec * 1000000 ) + now.usec; ! return retval; ! } /* *************** *** 134,140 **** * Returns the current time in timePtr. * * Side effects: ! * None. * *---------------------------------------------------------------------- */ --- 214,226 ---- * Returns the current time in timePtr. * * Side effects: ! * On the first call, initializes a set of static variables to ! * keep track of the base value of the performance counter, the ! * corresponding wall clock (obtained through ftime) and the ! * frequency of the performance counter. Also spins a thread ! * whose function is to wake up periodically and monitor these ! * values, adjusting them as necessary to correct for drift ! * in the performance counter's oscillator. * *---------------------------------------------------------------------- */ *************** *** 143,153 **** TclpGetTime(timePtr) Tcl_Time *timePtr; /* Location to store time information. */ { struct timeb t; ! ftime(&t); ! timePtr->sec = t.time; ! timePtr->usec = t.millitm * 1000; } /* --- 229,342 ---- TclpGetTime(timePtr) Tcl_Time *timePtr; /* Location to store time information. */ { + struct timeb t; ! /* Initialize static storage on the first trip through. */ ! ! /* ! * Note: Outer check for 'initialized' is a performance win ! * since it avoids an extra mutex lock in the common case. ! */ ! ! if ( !timeInfo.initialized ) { ! TclpInitLock(); ! if ( !timeInfo.initialized ) { ! timeInfo.perfCounterAvailable ! = QueryPerformanceFrequency( &timeInfo.curCounterFreq ); ! ! /* ! * Some hardware abstraction layers use the CPU clock ! * in place of the real-time clock as a performance counter ! * reference. This results in: ! * - inconsistent results among the processors on ! * multi-processor systems. ! * - unpredictable changes in performance counter frequency ! * on "gearshift" processors such as Transmeta and ! * SpeedStep. ! * There seems to be no way to test whether the performance ! * counter is reliable, but a useful heuristic is that ! * if its frequency is 1.193182 MHz or 3.579545 MHz, it's ! * derived from a colorburst crystal and is therefore ! * the RTC rather than the TSC. If it's anything else, we ! * presume that the performance counter is unreliable. ! */ ! ! if ( timeInfo.perfCounterAvailable ! && timeInfo.curCounterFreq.QuadPart != 1193182ui64 ! && timeInfo.curCounterFreq.QuadPart != 3579545ui64 ) { ! timeInfo.perfCounterAvailable = FALSE; ! } ! ! /* ! * If the performance counter is available, start a thread to ! * calibrate it. ! */ ! ! if ( timeInfo.perfCounterAvailable ) { ! DWORD id; ! InitializeCriticalSection( &timeInfo.cs ); ! timeInfo.readyEvent = CreateEvent( NULL, FALSE, FALSE, NULL ); ! timeInfo.calibrationThread = CreateThread( NULL, ! 8192, ! CalibrationThread, ! (LPVOID) NULL, ! 0, ! &id ); ! SetThreadPriority( timeInfo.calibrationThread, ! THREAD_PRIORITY_HIGHEST ); ! WaitForSingleObject( timeInfo.readyEvent, INFINITE ); ! CloseHandle( timeInfo.readyEvent ); ! } ! timeInfo.initialized = TRUE; ! } ! TclpInitUnlock(); ! } ! ! if ( timeInfo.perfCounterAvailable ) { ! ! /* ! * Query the performance counter and use it to calculate the ! * current time. ! */ ! ! LARGE_INTEGER curCounter; ! /* Current performance counter */ ! ! LONGLONG curFileTime; ! /* Current estimated time, expressed ! * as 100-ns ticks since the Windows epoch */ ! ! static const LARGE_INTEGER posixEpoch = { 0xD53E8000, 0x019DB1DE }; ! /* Posix epoch expressed as 100-ns ticks ! * since the windows epoch */ ! ! LONGLONG usecSincePosixEpoch; ! /* Current microseconds since Posix epoch */ ! ! EnterCriticalSection( &timeInfo.cs ); ! ! QueryPerformanceCounter( &curCounter ); ! curFileTime = timeInfo.lastFileTime.QuadPart ! + ( ( curCounter.QuadPart - timeInfo.lastCounter.QuadPart ) ! * 10000000 / timeInfo.curCounterFreq.QuadPart ); ! timeInfo.lastFileTime.QuadPart = curFileTime; ! timeInfo.lastCounter.QuadPart = curCounter.QuadPart; ! usecSincePosixEpoch = ( curFileTime - posixEpoch.QuadPart ) / 10; ! timePtr->sec = (time_t) ( usecSincePosixEpoch / 1000000 ); ! timePtr->usec = (unsigned long ) ( usecSincePosixEpoch % 1000000 ); ! ! LeaveCriticalSection( &timeInfo.cs ); ! ! ! } else { ! ! /* High resolution timer is not available. Just use ftime */ ! ! ftime(&t); ! timePtr->sec = t.time; ! timePtr->usec = t.millitm * 1000; ! } } /* *************** *** 439,442 **** --- 628,843 ---- } return tmPtr; + } + + /* + *---------------------------------------------------------------------- + * + * CalibrationThread -- + * + * Thread that manages calibration of the hi-resolution time + * derived from the performance counter, to keep it synchronized + * with the system clock. + * + * Parameters: + * arg -- Client data from the CreateThread call. This parameter + * points to the static TimeInfo structure. + * + * Return value: + * None. This thread embeds an infinite loop. + * + * Side effects: + * At an interval of clockCalibrateWakeupInterval ms, this thread + * performs virtual time discipline. + * + * Note: When this thread is entered, TclpInitLock has been called + * to safeguard the static storage. There is therefore no synchronization + * in the body of this procedure. + * + *---------------------------------------------------------------------- + */ + + static DWORD WINAPI + CalibrationThread( LPVOID arg ) + { + FILETIME curFileTime; + + /* Get initial system time and performance counter */ + + GetSystemTimeAsFileTime( &curFileTime ); + QueryPerformanceCounter( &timeInfo.lastCounter ); + QueryPerformanceFrequency( &timeInfo.curCounterFreq ); + timeInfo.lastFileTime.LowPart = curFileTime.dwLowDateTime; + timeInfo.lastFileTime.HighPart = curFileTime.dwHighDateTime; + + /* Initialize the working storage for the calibration callback */ + + timeInfo.lastPerfCounter = timeInfo.lastCounter.QuadPart; + timeInfo.estPerfCounterFreq = timeInfo.curCounterFreq.QuadPart; + + /* + * Wake up the calling thread. When it wakes up, it will release the + * initialization lock. + */ + + SetEvent( timeInfo.readyEvent ); + + /* Run the calibration once a second */ + + for ( ; ; ) { + + Sleep( 1000 ); + UpdateTimeEachSecond(); + + } + } + + /* + *---------------------------------------------------------------------- + * + * UpdateTimeEachSecond -- + * + * Callback from the waitable timer in the clock calibration thread + * that updates system time. + * + * Parameters: + * info -- Pointer to the static TimeInfo structure + * + * Results: + * None. + * + * Side effects: + * Performs virtual time calibration discipline. + * + *---------------------------------------------------------------------- + */ + + static void + UpdateTimeEachSecond() + { + + LARGE_INTEGER curPerfCounter; + /* Current value returned from + * QueryPerformanceCounter */ + + LONGLONG perfCounterDiff; /* Difference between the current value + * and the value of 1 second ago */ + + FILETIME curSysTime; /* Current system time */ + + LARGE_INTEGER curFileTime; /* File time at the time this callback + * was scheduled. */ + + LONGLONG fileTimeDiff; /* Elapsed time on the system clock + * since the last time this procedure + * was called */ + + LONGLONG instantFreq; /* Instantaneous estimate of the + * performance counter frequency */ + + LONGLONG delta; /* Increment to add to the estimated + * performance counter frequency in the + * loop filter */ + + LONGLONG fuzz; /* Tolerance for the perf counter frequency */ + + LONGLONG lowBound; /* Lower bound for the frequency assuming + * 1000 ppm tolerance */ + + LONGLONG hiBound; /* Upper bound for the frequency */ + + /* + * Get current performance counter and system time. + */ + + QueryPerformanceCounter( &curPerfCounter ); + GetSystemTimeAsFileTime( &curSysTime ); + curFileTime.LowPart = curSysTime.dwLowDateTime; + curFileTime.HighPart = curSysTime.dwHighDateTime; + + EnterCriticalSection( &timeInfo.cs ); + + /* + * Find out how many ticks of the performance counter and the + * system clock have elapsed since we got into this procedure. + * Estimate the current frequency. + */ + + perfCounterDiff = curPerfCounter.QuadPart - timeInfo.lastPerfCounter; + timeInfo.lastPerfCounter = curPerfCounter.QuadPart; + fileTimeDiff = curFileTime.QuadPart - timeInfo.lastSysTime; + timeInfo.lastSysTime = curFileTime.QuadPart; + instantFreq = ( 10000000 * perfCounterDiff / fileTimeDiff ); + + /* + * Consider this a timing glitch if instant frequency varies + * significantly from the current estimate. + */ + + fuzz = timeInfo.estPerfCounterFreq >> 10; + lowBound = timeInfo.estPerfCounterFreq - fuzz; + hiBound = timeInfo.estPerfCounterFreq + fuzz; + if ( instantFreq < lowBound || instantFreq > hiBound ) { + LeaveCriticalSection( &timeInfo.cs ); + return; + } + + /* + * Update the current estimate of performance counter frequency. + * This code is equivalent to the loop filter of a phase locked + * loop. + */ + + delta = ( instantFreq - timeInfo.estPerfCounterFreq ) >> 6; + timeInfo.estPerfCounterFreq += delta; + + /* + * Update the current virtual time. + */ + + timeInfo.lastFileTime.QuadPart + += ( ( curPerfCounter.QuadPart - timeInfo.lastCounter.QuadPart ) + * 10000000 / timeInfo.curCounterFreq.QuadPart ); + timeInfo.lastCounter.QuadPart = curPerfCounter.QuadPart; + + delta = curFileTime.QuadPart - timeInfo.lastFileTime.QuadPart; + if ( delta > 10000000 || delta < -10000000 ) { + + /* + * If the virtual time slip exceeds one second, then adjusting + * the counter frequency is hopeless (it'll take over fifteen + * minutes to line up with the system clock). The most likely + * cause of this large a slip is a sudden change to the system + * clock, perhaps because it was being corrected by wristwatch + * and eyeball. Accept the system time, and set the performance + * counter frequency to the current estimate. + */ + + timeInfo.lastFileTime.QuadPart = curFileTime.QuadPart; + timeInfo.curCounterFreq.QuadPart = timeInfo.estPerfCounterFreq; + + } else { + + /* + * Compute a counter frequency that will cause virtual time to line + * up with system time one second from now, assuming that the + * performance counter continues to tick at timeInfo.estPerfCounterFreq. + */ + + timeInfo.curCounterFreq.QuadPart + = 10000000 * timeInfo.estPerfCounterFreq / ( delta + 10000000 ); + + /* + * Limit frequency excursions to 1000 ppm from estimate + */ + + if ( timeInfo.curCounterFreq.QuadPart < lowBound ) { + timeInfo.curCounterFreq.QuadPart = lowBound; + } else if ( timeInfo.curCounterFreq.QuadPart > hiBound ) { + timeInfo.curCounterFreq.QuadPart = hiBound; + } + } + + LeaveCriticalSection( &timeInfo.cs ); + } *** ../tcl8.3.2base/src/tcl8.3.2/test/winTime.test Mon Apr 10 13:19:08 2000 --- ./tcl8.3.2/src/tcl8.3.2/test/winTime.test Wed Sep 6 14:55:30 2000 *************** *** 33,38 **** --- 33,64 ---- set result } {1969} + # Next test tries to make sure that the Tcl clock stays in step + # with the Windows clock. 3000 iterations really isn't enough, + # but how many does a tester have patience for? + + test winTime-2.1 {Synchronization of Tcl and Windows clocks} {pcOnly} { + set failed 0 + foreach { sys_sec sys_usec tcl_sec tcl_usec } [testwinclock] {} + set olddiff [expr { abs ( $tcl_sec - $sys_sec + + 1.0e-6 * ( $tcl_usec - $sys_usec ) ) }] + set ok 1 + for { set i 0 } { $i < 3000 } { incr i } { + foreach { sys_sec sys_usec tcl_sec tcl_usec } [testwinclock] {} + set diff [expr { abs ( $tcl_sec - $sys_sec + + 1.0e-6 * ( $tcl_usec - $sys_usec ) ) }] + if { ( $diff > $olddiff + 1000 ) + || ( $diff > 11000 ) } { + set failed 1 + break + } else { + set olddiff $diff + after 1 + } + } + set failed + } {0} + # cleanup ::tcltest::cleanupTests return |
Name change from tip/70.tip to tip/70.md.
|
| < | < | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | < > | | | | | | | | | | | | < > | < > | | | | | | | | | | | < > | | | | | < > | | < > | | | < < < > > > | | < > | | < < | > > | | | | | | | | | | | | | | < > | | | | < | > | | 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 | # TIP 70: A Relational Switch Control Structure Author: Bhushit Joshipura <[email protected]> Author: Donal K. Fellows <[email protected]> State: Withdrawn Type: Project Vote: Pending Created: 20-Oct-2001 Post-History: Tcl-Version: 8.5 ----- # Abstract This TIP proposes the introduction of a new control structure, _rswitch_, which is a relational parallel to switch-case control structure. It consists of two lists: condition list and situation-reaction list. At the maximum two conditions can be specified. Based on situation, reaction is executed. The situation is selected on "first true and only the first true" basis. # Rationale Theoretically only two controls - _if_ and _goto_ - are sufficient to implement all algorithms. However, languages provide more control structures for better representation of algorithms. To many structural programmers like me, a _switch_ statement gives much better picture of the program than equivalent _if_-_elseif_-...-_else_ chain. It pronounces the course of decision of a big chunk of program in a single statement, making understanding and maintaining software easier. It also helps to optimize the software better if it is written in _switch_ form. However, _switch_ is strictly data based i.e. _switch_ happens strictly on data value. The proposed _rswitch_ command is a control structure similar to \(and more general than\) _switch_. \(As a matter of fact, Tcl's _foreach_ control structure is a special case of its for control structure.\) Using _rswitch_ it should be possible to take decisions based on relations between entities. In response to comments on Revision: 1.2 of the draft, Bhushit Joshipura wrote [Re-edited]: Why rswitch? [Re-written] 1. if..elseif..else contains elements of surprize spread in the code. From maintenance point of view, once the _if_.._elseif_.._else_ code goes beyond horizon \(one display length\), burden of reference retention comes on human brain making maintenance bug-prone. 2. In case of _rswitch_, if a situation refers to one or more conditions, we had reduced this burden by stating upfront which variable is in the spotlight. The maintainer can then easily jump irrelavant cases. 3. In _if_.._elseif_.._else_, a string of three conditions \(with one of them being a \`not' string\) can mystify me for at least an hour. 4. In case of an _rswitch_ \(even in a situation which does not refer to any conditions\): > 1. \`and' is nested rswitch > 2. \`or' is a fall through case > 3. \`not' could be written as "default" case. \`not' free from \`and' and \`or' is less confusing. We can write almost a \`not-less' code using "default". > Logical connectives result into visual presentation. 5. Object Oriented Programming is trying to eliminate _switch-case_ statements by identifying localization of references and finding a heirarchy of data-actions. 6. In similar way one can think of _rswitch_ cases \(situations\). Identifying localized references \(w.r.t. situations\) and a heirarchy of situations-reactions. However, this is a research issue. Moreover, the writer does not need to be an artist to be able to write understandable code. # Implementation in Other Languages I queried about proposal of such a control structure in C to Dr. Dennis M. Ritchie in February 2001. \(At that time I thought only of bi-conditional relational switch. See a few pages down for currently proposed control structure.\) > Absence of relational switch I know this can be odd for other languages - but not for C. C is so near to machine and a relational switch could be ideal for many many machine-cycle saving situations. > Apart from machine-orientedness, it could avoid many usages of not-so-structured ?: operator. > It could simplify a lot of control and signal processing code too. > Why did C become more data-biased for a control structure? relational-switch(expr1,expr2){ case ==: statements; break; case > : statements; break; case < : statements; break; default: statements; break; } TCL need not be so optimized, as C has to be. However, clarity and maintainability remain formidable reasons for relational switch implementation. In a quick reply, Dr. Ritchie wrote back: > The relational switch idea is \(so far as I know\) for C a new suggestion, although I have no idea of all things that were proposed for the 1989 or 1999 C standards. If seems to hark back to the old Fortran GOTO statement IF (expression) 2, 3, 4 > which went to various places depending on whether the expression was -, 0 or \+. It's also a bit strange syntactically \(though it might work in the grammar\) in that the case values aren't expressions, but just operators. > Regards, Dennis" Thus the structure is absent from C and its whole family. It is absent from Pascal, PERL, BASIC, shell scripts - and of course, TCL. Fortran's computed goto is near to bi-conditional rswitch. \(That way Chimpanzees are near to Homo sapiens too.\) However, clarity of presentation of default and fall through are not achievable through computed goto. Mono-conditional rswitch, however, does not have a parallel in languages of my knowledge \(C, C\+\+, Java, Pascal, BASIC, Fortran, shell scripts\). # Grammar and Behavior Overall: rswitch {[condition(s)]} { <situation-1> { <reaction-block-1> } ... } The condition list may have no, one or two variables. A situation is legal if: 1. It is a valid expression or 2. If the condition list had at least one element 'x', \{$x $situation\} is a valid expression or > 1. If the condition list had exactly one element 'x', \{$situation $x\} is a valid expression or > 2. If the condition list had two elements 'x' and 'y', \{$x $situation $y\} is a valid expression or 3. If the condition list had two elements 'x' and 'y' and \{$situation $y\} is a valid expression or 4. If $situation == "default" A reaction block is legal if: 1. It is not the last block and $reactionBlock == "-" \(fall through\) or 2. It is a valid TCL action block Let us call a non-default extracted valid expression a SITUATION. At execution, reaction block following or fell through by the first and only the first SITUATION that becomes true, is executed. In case no SITUATION becomes true and default situation is present, reaction block following or fell through by default statement is executed. Default situation is not necessary for operation of rswitch. An rswitch without any situation-reaction block is grammatically valid. # Sample Invocations # Full length condition block. Second condition perhaps got redundant with maintenance. rswitch {$a $b} { {> $c} - {< $d} { puts "$a is either > $c or < $d or both" } {< $c} { # Full length condition block. Second condition is used. rswitch {$a $d} { > { puts "$a is < $c AND > $d" } == { puts "$a and $d are equal and they are < $c" } default { puts "$a is < $c BUT <= $d" puts "should never come here" } } } {3 > } { puts "$a == $c, $a >= $d and $b <= 3" } default { puts "$a == $c, $a >= $d and $b >= 3" } } # Contrast Contrast above code with its if-elseif-else equivalent. Notice that: 1. Both the examples have same effect. 2. Both examples are indented with the same style. if {($a > $c) || ($a < $d)} { # could you see a maintenance nightmare that could have arisen when # reference to $b were eliminated? puts "$a is either > $c or < $d or both" } elseif {$a < $c} { if {$a > $d} { puts "$a is < $c AND > $d" } elseif {$a == $d} { puts "$a and $d are equal and they are < $c" } else { puts "Pop-up question: What should we have here? puts "$a is < $c BUT <= $d" puts "should never come here" } } elseif {3 > $b} { puts "$a == $c, $a >= $d and $b <= 3" } else { puts "$a == $c, $a >= $d and $b >= 3" } # Responses to Revision 1.2 Revision 1.3 tries to reflect suggestions from various of the following contributors. Thanks. John Ousterhaut wrote: > This is certainly a novel suggestion, but I'm not sure how useful it is. The proposed new command doesn't seem much clearer or much more |
︙ | ︙ | |||
273 274 275 276 277 278 279 | can accept multiple conditional relationships in a single statement. > I can also think of another usage of 'rswitch' which doesn't take any arguments at all. A vanilla version which is just replacement to if-elseif-elseif-..-else structure but only that code is more easier to read... | | | | | | < > | | | | < > | | | | | < | > | | | | | | < | > | | | | | | | | | | < > | | > | 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 | can accept multiple conditional relationships in a single statement. > I can also think of another usage of 'rswitch' which doesn't take any arguments at all. A vanilla version which is just replacement to if-elseif-elseif-..-else structure but only that code is more easier to read... rswitch { ($a > 4): /* block 1 */ ($b < 100): /* block 2 */ ($c > 5 ): /* block 3 */ ($d == 10): /*block 4 */ } Don Porter wrote: > Rather than defining two forms of the command, mono-conditional and bi-conditional, why not use the power of Tcl to allow for both and even more possibilities within a singleform? > Consider: rswitch $formatString { $sub1 $body1 ... $subN $bodyN } > Then have [rswitch] construct the Tcl expressions to be tested using [format]: format $formatString $sub1 > So you could have: rswitch {$a %s $b} { > {puts "$a is greater than $b"} < {puts "$a is less than $b"} == {puts "$a equals $b"} } > or rswitch {$a %s} { 1 {puts "$a > 1"} 5 {puts "$a > 5"} 15 {puts "$a > 15"} {>$b} {puts "$a > $b"} {<$b} - > {==$b} {puts "$a <= $b"} } > Extending this idea further, consider the possibility of using [format] to create the expression like so: eval [linsert $sub1 0 format $formatString] > Then the substitutions could be lists of multiple values to substitute into multiple %-conversion specifiers in the format string, allowing for the construction of quite elaborate expressions. Brent Welch wrote > I like Don's suggestion. I'm reminded of the switch statement in the tclhttpd state machine, crafted by Steve Uhler: set state [string compare $readCount 0],$data(state) switch -glob -- $state { 1,start { # Read something in the start state } 0,start { # Read empty line in the start state 1,mime { # Read something in the mime state } 0,mime { # Read blank line in the mime state } -1,* { # Read error in any state } default { # Unexpected condition } } > I had had a bunch of nested if-then-else's, of course. With an artful creation of the switch value and the power of things like glob, you can really create compact, expressive switch statements already. # Sample Implementation Will be provided later. # Copyright This document is placed in public domain. |
Name change from tip/71.tip to tip/71.md.
|
| < | < | | | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 71: Tk Bitmap Image Improvements Author: Chris Nelson <[email protected]> Author: Kevin Kenny <[email protected]> Author: Eric Melski <[email protected]> Author: Donal K. Fellows <[email protected]> State: Withdrawn Type: Project Vote: Pending Created: 26-Oct-2001 Post-History: Tcl-Version: 8.5 ----- # Abstract Tk has a number of pre-defined bitmaps \(10 on all platforms\) but it lacks a number of bitmaps useful for creating GUI elements. This TIP adds several such bitmaps \(as bitmap images\). # New Bitmaps Many complex widgets like comboboxes, spinboxes, etc. require arrows pictures on buttons. While newer releases of Tk have added more widgets, there will always be some unforeseen need for new or customized widgets. One example is a menubutton which, according to the Microsoft Windows User Experience <http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnwue/html/welcome.asp> , should have a downward arrow on the right side. With compound buttons, it is not hard to do: button .mb -text Tools -image downarrow -compound right but there is no stock down-arrow image. I propose to add 12 bitmap images providing all four directions \(up, down, left, and right\) in three sizes \(3x2, 5x3, and 7x4\) in black. The down arrows would look something like: @@@@@@@ @@@@@ @@@ .@@@@@. .@@@. .@. ..@@@.. ..@.. ...@... I propose the following names: arrow_u7x4 arrow_u5x3 arrow_u3x2 arrow_d7x4 arrow_d5x3 arrow_d3x2 arrow_l7x4 arrow_l5x3 arrow_l3x2 arrow_r7x4 arrow_r5x3 arrow_r3x2 I'm mindful of the fact that adding new predefined bitmap images has the potential to collide with application-defined images or other commands but I'm unsure of the workaround for that. # Reference Implementation SourceForge patch 475332 provided a reference implementation of a previous version of this proposal <http://sf.net/tracker/?func=detail&aid=475332&group_id=12997&atid=312997> . This version is not implemented yet. # Commentary _Donal K. Fellows <[email protected]> writes:_ > Previous versions of this TIP proposed fixing the problem using bitmaps instead of bitmap images and added an infrastructure for tracking those bitmaps. Since I think that ultimately we should be getting rid of bitmaps and instead using something based on the image infrastructure \(which already has proper introspection support\) those parts of this TIP have been removed. However, making the changes to effect the switch to using bitmap images instead of bitmaps for things like stippes, cursors, etc. lies outside the scope of this TIP. _Donal K. Fellows <[email protected]> writes:_ > In the long period since this TIP was proposed, the world of GUIs has moved on somewhat. Although the requirement for arrows remains the same, the solutions proposed in this TIP \(both originally and as it now stands\) do not permit the sort of graphical snazziness that modern users tend to expect. Nor is there a sufficient range of sizes for a reasonable selection to be available for a modern display; even the largest of those arrows would look unusably tiny on my desktop! This indicates that a completely different solution is required, which in turn would be better stated as a separate TIP. # Copyright This document has been placed in the public domain. |
Name change from tip/72.tip to tip/72.md.
|
| < | < | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 72: 64-Bit Value Support for Tcl on 32-Bit Platforms Author: Donal K. Fellows <[email protected]> State: Final Type: Project Vote: Done Created: 05-Nov-2001 Post-History: Tcl-Version: 8.4 ----- # Abstract This TIP adds the capability to perform computations on values that are \(at least\) 64-bits wide even on 32-bit platforms. It also adds support for handling files that are larger than 2GB large on those platforms \(where supported by the underlying platform and filing system\). # Rationale There have been a number of requests, and from a whole range of application areas, for Tcl to be enhanced to handle 64-bit values even on platforms where that is larger than the native word size, and the vast majority of C compilers support a large enough arithmetic type \(often called _long long_ though other names are common on the Windows platform.\) Such areas include: * _large-file support_ for people working with lots of data. Note that at the moment Tcl cannot even report the file type for a file that is larger than 2GB in size. * _large value support_ for people working with network addresses \(this is likely to come up more in the future with IPv6.\) However, a number of existing algorithms assume that integer arithmetic operations wrap at 32-bits \(demonstrating the need for _semantic backward-compatibility_ so termed because a recompile of the C portions of the relevant code will not fix the problem\) and there are many existing extensions that assume a particular word-size too \(requiring _syntactic backward-compatibility_ because recompilation will probably cure the problem.\) Hence any upgrade of Tcl's functionality must be done carefully so as to preserve as much backward compatibility as possible. # Proposed for Changes To resolve this problem, I will introduce: 1. A new pair of types at the C level to represent signed and unsigned values with a width of at least 64-bits. These types will be called _Tcl\_WideInt_ and _Tcl\_WideUInt_ respectively. On 64-bit platforms \(and 32-bit platforms where there is no compiler support for arithmetic 64-bit types\) these will be typedef'ed to _long_ to preserve as much inter-platform compatibility as possible. > The type names are based on the term _Wide_ as opposed to either _Long_ or _LongLong_ because the first causes a problem with existing Tcl APIs \(_Tcl\_GetLongFromObj_ for example\) and the second because it is both longer and less mnemonic. Not all Tcl platforms are built with compilers that understand _long long_ in the first place, and the major factor in its favour at the C level was almost certainly the fact that it did not introduce any new reserved words into the C syntax which would have had a major backward-compatibility impact - we are not bound by such things and can choose to suit ourselves. 2. A new field of type _Tcl\_WideInt_ in the internalRep union of the _Tcl\_Obj_ type. Note that this is 100% backward compatible since the union already contains a field that is a pair of pointers \(each of which I assume to be at least 32-bits wide.\) 3. A new object type of 64-bit wide values together with accessor functions to create, modify and retrieve from objects of that type called _Tcl\_NewWideIntObj_, _Tcl\_SetWideIntObj_ and _Tcl\_GetWideIntFromObj_ \(on platforms where _Tcl\_WideInt_ is not distinct from _long_, these will be all redirected to the previously existing integer type.\) 4. The [expr] command shall be reworked so that: > \* If a constant looks like a signed integer \(i.e. it lies between INT\_MIN and INT\_MAX inclusive\) it is treated as such. Otherwise if it looks like an integer of any size, an attempt will be made to treat it like a wide integer, and if that fails or it doesn't look like an integer at all, it will be treated as a double. _Note_ that this will be a source of a potential backwards incompatibility with scripts that include values that are meant to be unsigned integers. > \* With arithmetic operations, the output will be a double if at least one of the operands is a double, a wide integer if at least one of the operands is a wide integer, and a normal integer otherwise. \(The main exception to this will be the left and right shift operations where the type of the second operand will not affect the type of the result.\) > \* The _int\(\)_ pseudo-function will always return a non-wide integer \(converting by dropping the high bits\) and the new pseudo-function _wide\(\)_ will always return a wide integer \(converting by sign-extending.\) On platforms without a distinct 64-bit type, these operations will behave identically. > \* User-defined functions will be able to gain access to the wide integer through an extra _wideValue_ field in the _Tcl\_Value_ structure and TCL\_WIDE\_INT \(which will be the same as TCL\_INT on platforms without a distinct 64-bit type\) value in the _Tcl\_ValueType_ enumeration. 5. The [incr] command will be able to increment variables containing 64-bit values correctly, but will only accept 32-bit values as amounts to increment by. 6. _Tcl\_Seek_ and _Tcl\_Tell_ \(together will all channel drivers\) will be updated to use the new 64-bit type for offsets \(which will reflect at the Tcl level in the [seek] and [tell] commands\) though a compatibility interface for old extensions that do not supply a channel driver will be maintained \(though the size of offset reportable through the interface will naturally be limited.\) 7. _Tcl\_FSStat_ and _Tcl\_FSLstat_ will all be updated to use a stat structure reference that can contain 64-bit wide values. This will enable various [file] subcommands \(and [glob] with some options\) to work correctly with files over 2GB in size. Note that there is no neat way to do this in a backward compatible way as there is currently no guarantee on which fields will actually be present in the structure, but those functions have never been available outside an alpha... > Because the name of a suitable structure varies considerably between platforms, a new type, _Tcl\_StatBuf_, will be declared to be the type of the structure which a pointer to should be passed to the stat-related functions. A new function, _Tcl\_AllocStatBuf_, will be provided to allow extensions to allocate a buffer of the correct size whatever the platform. > Note that _Tcl\_Stat_ will written to contain backward-compatability code so that code that references it will work unchanged. 8. The _format_ and _scan_ commands will gain a significance to the _l_ modifier to their integer-handling conversion specifiers \(d, u, i, o and x\) which will tell them to work with 64-bit values \(if those are not the default for the platform anyway.\) 9. The _binary_ command will gain new _w_ and _W_ specifiers for its _format_ and _scan_ subcommands. These will operate on 64-bit wide values in a fashion analogous to the existing _i_ and _I_ specifiers \(i.e. smallest byte to largest, and largest byte to smallest respectively.\) 10. New compatibility functions will also be provided, because not all platforms have convenient equivalent functions to _strtoll_ and _strtoull_. 11. _Tcl\_LinkVar_ will be extended to be given the ability to link with a wide C variable \(via a TCL\_LINK\_WIDE\_INT flag\). 12. The _tcl\_platform_ array will gain a new member, _wordSize_, which will give the native size of machine words on the host platform \(actually whatever _sizeof\(long\)_ returns.\) # Summary of Incompatibilities and Fixes The behaviour of expressions containing constants that appear positive but which have a negative internal representation will change, as these will now usually be interpreted as wide integers. This is always fixable by replacing the constant with _int\(_constant_\)_. Extensions creating new channel types will need to be altered as different types are now in use in those areas. The change to the declaration of _Tcl\_FSStat_ and _Tcl\_FSLstat_ \(which are the new preferred API in any case\) are less serious as no non-alpha releases have been made yet with those API functions. Scripts that are lax about the use of the _l_ modifier in _format_ and _scan_ will probably need to be rewritten. This should be very uncommon though as previously it had absolutely no effect. Extensions that create new math functions that take more than one argument will need to be recompiled \(the size of _Tcl\_Value_ changes\), and functions that accept arguments of any type \(_TCL\_EITHER_\) will need to be rewritten to handle wide integer values. \(I do not expect this to affect many extensions at all.\) # Why Tcl\_WideInt? I chose the name _Tcl\_WideInt_ for the type because it represents a wider-than-normal integer. Alternatives that were considered and rejected were: Tcl\_LongLong: This takes its name from the name of the underlying C type used in many UNIX compilers, but that in turn was chosen because it meant that no new keywords would be added to the language, and not out of any feeling that the type name itself is of any wider merit. Seeing as Tcl is a keyword-less language, there is no particular reason for going down this route \(which would lead to things like a _longlong\(\)_ type conversion function added to the [expr] command, which is really very ugly indeed...\) It is also not universally the name of the underlying type; the Windows world is different \(as usual.\) Tcl\_Int64: This name, by contrast, comes more from the Windows world. It's major problem is that it specifies eternally what the size of the type is, whereas at some point in the future \(when 64-bit words are the norm\) we may want to support something wider still \(though I do not yet know what uses we would put 128-bit integers to.\) I believe that the name of a type is part of its specification, but that the size of the type is less so. _Tcl\_Int64_ is also ugly when it comes to derivations of the name for things like the type converter in [expr] \(again\) and the names of variables containing values of the type \(internally, as formal parameters, and as fields of structures\) and may well clash on systems where the C compiler gives real meaning to _int64_ by default. By contrast, _Tcl\_WideInt_ lends itself well to generating variable names \(_wideValue_, _widePtr_, etc., and even just plain _w_ in the implementation of the bytecode execution engine\) which, as the person implementing the changes, was a major consideration. # Copyright This document has been placed in the public domain. |
Name change from tip/73.tip to tip/73.md.
|
| < | | | | | | < | | > | | | | | | | | | | | | | | | | > | 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 | # TIP 73: Export Tcl_GetTime in the Public API State: Final Type: Project Tcl-Version: 8.4 Vote: Done Post-History: Author: Kevin Kenny <[email protected]> Created: 03-Nov-2001 ----- # Abstract This TIP proposes that the existing _TclpGetTime_ function be renamed to be _Tcl\_GetTime_ and included in the published API. # Rationale The Tcl library provides a uniform abstraction, _TclpGetTime_ that is implemented on each of the platforms to retrieve absolute time in a _Tcl\_Time_ object. This function is highly useful outside the Tcl library itself, since it hides a very complex set of interfaces, particularly on Windows, where several hundred lines of code enable its use for high-precision measurements. For this reason, it ought to be made part of the public API. # Proposed Change The existing _TclpGetTime_ procedure shall be renamed to be _Tcl\_GetTime_, and its declaration shall be added to _tcl.decls_. void TclpGetTime( Tcl_Time* timePtr ); A definition of _TclpGetTime_ as a stub procedure that simply invokes _Tcl\_GetTime_ shall be retained in _tclInt.decls_ for compatibility with existing Stubs-enabled extensions that invoke it. This change requires no other change to the public headers; the _Tcl\_Time_ structure is already exported in _tcl.h_. # Copyright Copyright © 2001 by Kevin B. Kenny. Distribution in whole or part, with or without annotations, is unlimited. |
Name change from tip/74.tip to tip/74.md.
|
| < | < | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 74: wm stackorder command Author: Mo DeJong <[email protected]> State: Final Type: Project Vote: Done Created: 12-Nov-2001 Post-History: Tcl-Version: 8.4 ----- # Abstract Tk provides no means to query the stacking order of toplevel windows. This functionality would be useful to applications that wished to save and restore the state and relative order of each toplevel. This functionality would also make it possible to write test cases for window manager related commands like focus, raise, and lower. This document suggests a new _wm stackorder_ command to address this deficiency. # Specification wm stackorder window ?isabove|isbelow? ?window? The following would return a list of all the toplevels on the display: % wm stackorder . The returned list would include the passed in window and its children. Only those toplevel windows that are mapped would be returned. The stacking order is from lowest to highest, so the last element in the list is the window on top of the display. The _wm stackorder_ command could also be used to compare the relative position in the stackorder. The following command would return true if _.a_ was higher in the stacking order compared to _.b_. % wm stackorder .a isabove .b The _isbelow_ usage is analogous: % wm stackorder .b isbelow .a One additional C API would be added. It would accept a Tk window and return an array of Tk windows in stacking order. This function would be implemented in the platform specific window manager code, such as _tkUnixWm.c_. This function signature is subject to change. TkWindow ** TkWmStackorderToplevel(TkWindow *parentPtr); # Rationale Tk exposes a number of features related to toplevel windows through the _wm_ command. While a user can set the relative position of a toplevel in the stacking order, it is not currently possible to query the stacking order for toplevel windows. Users are frustrated by the lack of access to this information. This is a posting to news:comp.lang.tcl by Jim Ingham is typical: > _This seems pretty basic, but for the life of me I can't figure out how to determine the stacking order of Tk toplevels. I want to save away the currently open windows in my application, and I would like to preserve both positions _and_ window stacking order. I know how to get the positions of toplevels, but I can't figure out how to get the window manager's stacking order. Should be in the _wm_ commands, but nothing leaps out at me. What am I missing?_ It is simply not logical to provide a means to manipulate the stacking order of toplevel windows without also providing a way to query the stacking order. This functionality is needed, if only to help with the authoring of test cases. For example, one could verify that a call to _wm raise_ actually worked by checking to see if the stacking order was changed. The second form of the wm stackorder command provides an easy way to compare the relative position of windows in the stacking order. This sort of boolean check is commonly needed in test cases. One could implement the same logic by querying the whole list, searching it twice to find the indices, and then comparing the indices, but the code would not be as easy to understand and it would not be as efficient. The _wm stackorder_ command also has an extra benefit, it provides an easy way to query the currently mapped toplevel windows. It is not difficult to write a procedure that recursively descends through each window and filters out those windows that are not mapped toplevels. This _wm stackorder_ command would just make it easier to query this list. # Reference Implementation A reference implementation has been created for X windows and Win32 systems. The X version makes us of the _XQueryTree\(\)_ function while the Windows version depends on the _EnumWindows\(\)_ Win32 API. Both implementations query the stacking order of toplevel windows in the root window. The patch, test cases, and documentation changes can be found in Tk patch 481148 at SourceForge. Porting to MacOS and MacOS X will require assistance from area maintainers. # Alternatives Instead of adding a new _wm stackorder_ command, one could adjust the behavior of _winfo children_. The documentation currently reads: winfo children window: Returns a list containing the path names of all the children of window. The list is in stacking order, with the lowest window first. Top-level windows are returned as children of their logical parents. A user would no doubt conclude that the stacking order was maintained for both toplevels and contained widgets. Unfortunately, the implementation only tracks the stacking order for contained widgets. % toplevel .t % pack [button .t.b1] % pack [button .t.b2] % winfo children .t .t.b1 .t.b2 % raise .t.b1 % winfo children .t .t.b2 .t.b1 Tk does not track stacking order changes for toplevels. % toplevel .t2 % winfo children . .t .t2 % raise .t % winfo children . .t .t2 There are two possible ways to "fix" the _winfo children_ command so that it would return toplevels in stacking order. One could call the _TkWmStackorderToplevel\(\)_ function and use the results to sort any toplevels that would be returned by _winfo children_. The other option would be to resort the _TkWindow->childList_ as toplevels are moved up and down in the stacking order. Both of these alternatives have some serious implementation issues. The _TkWmStackorderToplevel\(\)_ function is very slow. The X based implementation recurses through each window in the Tk hierarchy to create a mapping of wrapper window ids to _TkWindow_s. The function then queries the X server to find each X window that is a child of the root screen and checks to see if the window exists in the mapping. When compared to _winfo children_, which just loops over an in-memory list, it is easy to see why _wm stackorder_ is so much slower. % for {set i 0} {$i < 10} {incr i} {toplevel .t$i} % time {winfo children .} 100 34 microseconds per iteration % time {wm stackorder .} 100 394 microseconds per iteration It would not be wise to make the _winfo children_ command an order of magnitude slower just to add a new capability. One also needs to remember that the _winfo children_ command is often used recursively, so any slowdown would be multiplied by the depth of the window hierarchy. The second option would be to keep the _TkWindow->childList_ sorted as toplevels are raised and lowered either by the application or the window manager. This would imply binding to the <Circulate> event under X. While the <Circulate> event is defined in Tk, it does not seem to actually be delivered by the window manager. In any event, this seems like an area ripe for incompatibility and error. Even if one of the above fixes for the _winfo children_ command was doable, it still would not satisfy user's needs. One would be able to compare the relative stacking order of two toplevels that have the same parent. % toplevel .t1 % toplevel .t2 % winfo children . {.t1 .t2} Unfortunately, it would not be possible to compare the stacking order of two toplevel windows that have different parents. % toplevel .t1 % toplevel .t1.t2 # No help here! % winfo children . .t1 % winfo children .t1 .t1.t2 It would not even be possible to query the position of the . window in the stacking order since it does not have a parent window that can be passed to _winfo children_. Since modifying _winfo children_ could cause some serious problems and would ultimately be ineffective, this alternative was rejected. Instead, the documentation for the _winfo children_ command should be updated to indicate that toplevel windows are not returned in stacking order. # Risks It is not entirely clear what risks would be associated with this TIP. The logic of the _wm stackorder_ command is rather insulated from the rest of the Tk core. Changing the implementation of _Tk\_RestackWindow\(\)_ and keeping the _TkWindow->childList_ up to date w.r.t. external changes would be more risky since it could affect other parts of the core. Doing an explicit query to find the stacking order seems a lot less error prone when compared to monitoring events from the window manager. We might speed things up by also storing wrapper pointers in the map table so that a call to _Tk\_IdToWindow\(\)_ with a wrapper id would work, but it is not clear that would help since the _XQueryTree\(\)_ likely takes up most of the function processing time. It is also not known how difficult or costly this functionality will be to implement on Mac OS, or Mac OS X. # Copyright This document has been placed in the public domain. |
Name change from tip/75.tip to tip/75.md.
|
| < | < | | | | | | | | | | | > | | | | | < | > | | | | | | | | | | | | | | | | | | | < > | | < < | > > | | | | | | | | | | | | < > | | < > | | < > | | < < > > | | | | > | 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 | # TIP 75: Refer to Sub-RegExps Inside 'switch -regexp' Bodies Author: Donal K. Fellows <[email protected]> Author: János Holányi <[email protected]> Author: Salvatore Sanfilippo <[email protected]> State: Final Type: Project Vote: Done Created: 28-Nov-2001 Post-History: Discussions-To: http://purl.org/mini/cgi-bin/chat.cgi Keywords: switch,regexp,parentheses Tcl-Version: 8.5 ----- # Abstract Currently, it is necessary to match a regular expression against a string twice in order to get the sub-expressions out of the matched string. This TIP alters that so that those sub-exps can be substituted directly into the body of the script to be executed. # Rationale Similarly to the regexp -- <RE> $string matchvar submatchvar ... of Tcl and the interact -re <RE> { set matches "$interact_out(0,string) $interact_out(1,string) ..." } of Tcl/Expect, it would be very helpful and would also make Tcl more consistent if the [switch] command of Tcl would support references to parenthesized REs inside the switch patterns from the bodies associated to each of the patterns. As it is, it is currently necessary to match the regular expression against the string twice to obtain this information. # Specification The easiest way to get the information is to place it into a variable. All that remains is a way to specify which variable should receive the information. This is done by a new option to the [switch] command: _-matchvar_. The argument to this optiongives the name of a variable in which will be placed a Tcl list of the matches discovered by the RE engine, such that the part of the string that was matched is given by [lindex $var 0], the first parenthesis by [lindex $var 1], etc. The alternative to this is to use the name of an array, but this is more expensive. The indices which the match occurred at can also be sometimes useful. Therefore, the new option _-indexvar_ will also be provided which will name a variable into which a list of match indices \(each a two item list of values in the same way that [regexp -indices] computes\) will be placed. It will be legal for both -matchvar and -indexvar to be specified in the same [switch] command, but only if the matching mode is -regexp. \(The other kinds of match modes always match against the whole string anyway.\) Both variables \(if specified, of course\) will contain the empty list if the _default_ branch is taken. # Example set string "some long complicated message" switch -matchvar foo -indexvar bar -regexp -- $string { {\w*(e)\w*} { puts "matched [lindex $foo 0] with 'e' at [lindex $bar 1 0]" } default { puts "no words containing a letter 'e' at all" } } # Alternatives Actually, no new syntax is needed to achieve the mentioned ability. The solution could adopt the behavior of [regsub] _\(description taken from regsub\(n\)\)_: > If subSpec contains a \`&' or \`\\0', then it is replaced in the substitution with the portion of string that matched exp. If subSpec contains a \`\\_n**, where _n_ is a digit between 1 and 9, then it is replaced in the substitution with the portion of string that matched the _n_-th parenthesized subexpression of exp. Additional backslashes may be used in subSpec to prevent special interpretation of \`&' or \`\\0' or \`\\n' or backslash. This has the disadvantage of being incompatible with existing code that makes use of the -regexp option to [switch] and which may well have characters matching the above sequences inside already. Another alternative can be to specify either -submatches, or -subindexes and use three elements for every switch case. The first is the regexp, the second the list of vars like in the [regexp] command, and the last the script to execute. set string [getSomeComplexProtocolLine] switch -regexp -submatches -- $string { {EHLO (.*)} {match heloarg} { puts "Helo $heloarg" } {MAIL FROM: <(.*)@(.*)>} {match user host} { puts "Mail from $user at $host" } {QUIT} {} { exit } default {} { puts "What a strange SMTP command!" } } Usually submatches have quite logical names, so it is possible that to refer they by name instead of to use [lindex] can be more comfortable. Another minor advantage of this is that variable names are very near the script, so it shouldn't be hard to follow what the script is doing. On the other side this changes a well-known fact of switch getting as input two elements for every case; the main proposal of this TIP has the advantage of leaving that feature of the [switch] command as an invariant. This makes the overall implementation of the feature easier, and also makes it easier to tell people how to use. And it allows for trivial obtaining of both the matched string and the range of the input string that matched. Of course, in that case you could just have four values for each entry, but that is getting baroque. # Reference Implementation <http://sf.net/tracker/?func=detail&aid=848578&group\_id=10894&atid=310894> # Copyright This document has been placed in the public domain. |
Name change from tip/76.tip to tip/76.md.
|
| < | | | | | | < | | | > | | | | | | | | | | | | | | | | | | | | | < | > | | | | | < > | | | | | | | | | | | < > | | | | | | | | | | | | < > | | | | | < | > | | > | 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 | # TIP 76: Make 'regsub' Return a String State: Final Type: Project Tcl-Version: 8.4 Vote: Done Post-History: Author: Bruce Hartweg <[email protected]> Author: Donal K. Fellows <[email protected]> Created: 29-Nov-2001 ----- # Abstract This TIP proposes altering the [regsub] command so that it can return the substituted string as the result of the command. # Rationale In many of the most common uses of the [regsub] command, the substituted string is used only once in the immediately following command. However, the [regsub] command only provides the substituted string via a variable, with the result of the command itself being the number of substitutions performed. For many uses of the command, it is the substituted string though that is the most useful result, especially if some other transformation is going to be applied to it \(like further [regsub] commands or some other Tcl command like one of the [string] subcommands or [subst].\) This TIP proposes a mechanism for providing the ability to return the string as the command's result, and in a way that is backward-compatible with existing scripts. # Specification regsub ?switches? exp string subSpec ?varName? If _varName_ is supplied the new string is written there and the number of substitutions are returned \(same as current behavior\). If _varName_ is not supplied than the new string is returned as the result of the [regsub] command. # Reference Implementation This is a pretty easy change, although I do not currently have an environment where I can actually build and test this the following should create the desired behavior. File: _tcl/generic/tclCmdMZ.c_ Function: _Tcl\_RegsubObjCmd_ Currently \(v 1.52\): if (objc - idx != 4) { Tcl_WrongNumArgs(interp, 1, objv, "?switches? exp string subSpec varName"); return TCL_ERROR; } which should be changed to: objc -= idx; if (objc != 3 || objc != 4) { Tcl_WrongNumArgs(interp, 1, objv, "?switches? exp string subSpec ?varName?"); return TCL_ERROR; } and then at the end change this: if (Tcl_ObjSetVar2(interp, objv[3], NULL, resultPtr, 0) == NULL) { Tcl_AppendResult(interp, "couldn't set variable \"", Tcl_GetString(objv[3]), "\"", (char *) NULL); result = TCL_ERROR; } else { /* * Set the interpreter's object result to an integer object * holding the number of matches. */ Tcl_SetIntObj(Tcl_GetObjResult(interp), numMatches); } to this: if (objc == 4) { if (Tcl_ObjSetVar2(interp, objv[3], NULL, resultPtr, 0) == NULL) { Tcl_AppendResult(interp, "couldn't set variable \"", Tcl_GetString(objv[3]), "\"", (char *) NULL); result = TCL_ERROR; } else { /* * Set the interpreter's object result to an integer object * holding the number of matches. */ Tcl_SetIntObj(Tcl_GetObjResult(interp), numMatches); } } else { /* * No varname supplied, return string as result */ Tcl_SetObjResult(interp, resultPtr); } And then minor updates to the man page to show that _varName_ is optional. # Copyright This document has been placed in the public domain. |
Name change from tip/77.tip to tip/77.md.
|
| < | < | | | | | | | | > | | | | | | | | | | | | < | > | | | | | | < < | > > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | < < > > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 77: Support for Nested Paired Item Lists Author: Christian Williams <[email protected]> State: Withdrawn Type: Project Tcl-Version: 8.5 Vote: Pending Created: 07-Dec-2001 Obsoleted-By: 111 Post-History: ----- # Abstract Tcl arrays can be transformed to and from lists using the _array get_ and _array set_ commands. This TIP proposes a new command for working directly these paired lists, and extending them to allow nesting in a manner analogous to [[22]](22.md). # Rationale Tcl lists provide only ordinal access to their items; often it makes more sense to access items by pre-assigned descriptive names. This can be easily accomplished with Tcl arrays. Consider these alternatives: set urlList { http tcl.activestate.com 80 /index.html } array set urlArray { proto http host tcl.activestate.com port 80 uri /index.html } Clearly the array approach promotes more readable code \(_$urlArray\(host\)_ versus _[lindex $urlList 1]_\). However, it's quite unwieldy and sometimes expensive to use arrays to access members of many sets of structured data, particularly when that data contains nested structures. Consider this structured data: set data { text {ignored-data} valid-styles { justification {left centered right full} font {courier helvetica times} } } Extracting items from structures like this can be accomplished by multiple _array set_ commands: array set dataArray $data array set validStylesArray $dataArray(valid-styles) puts "Justification: $validStylesArray(justification)" To modify an item in _struct_, we need some pretty ugly code: array set dataArray $struct array set validStylesArray $dataArray(valid-styles) set validStylesArray(justification) {left} set dataArray(valid-styles) [array get validStylesArray] set data [array get dataArray] Clearly, all this setting and getting of arrays imposes a rather high overhead; many variables are created and moved around. Also, if this is occurring in a loop, then care must be taken to unset the _dataArray_ and _validStylesArray_ arrays first. In contrast, a C programmer may expect that code to look more like this: data->valid-styles->justification = 'left'; Extending Tcl with a command supporting nested, paired item lists would permit very efficient and readable handling of these useful data structures. # Specification Under this proposal, a new command named _pair_ \(referring to the pairs of name/value list items it works with\) would be added to the Tcl core. A well-formed paired list is defined as a well-formed Tcl list whose length is evenly divisible by two. In each pair of list items, the first item gives the name of the pair, and the second gives the value. Paired lists may be nested by placing a valid paired list in the second \(value\) item of any pair. Note that the pairs are not grouped together into a two-item list as in TclX's keyed lists. Tcl's _array get_ command returns a well-formed paired list. The syntax for the new _pair_ command would be: pair option variable node ?newValue? Valid values for the _options_ argument include _get_, _set_, _unset_, _exists_, and _append_. These subcommands are equivalent to the existing Tcl commands of the same names. The _variable_ argument is the name of a Tcl variable; it is always referred to by name, not by its value \(that is, no _$_\). Generally, the variable would contain a well-formed, and optionally nested, paired list. The _node_ argument is a well-formed Tcl list of zero or more items specifying the route to the item we're interested in. For example: set data { text {ignored-data} valid-styles { justification {left centered right full} font {courier helvetica times} } } puts "Justification: [pair get data {valid-styles justification}]" displays "Justification: left centered right full". If the _data_ argument contains zero items, then the "root" node of the variable is targeted -- that is, the entire variable: pair set node {} new-value puts $node displays "new-value". If a non-existent node is targeted using the _get_ or _unset_ options, an error is returned: unset x pair get x {first second third} -> no such value If a non-existent node is targeted using the _set_ or _append_ options, the node, and any parent nodes, are created. unset x pair set x {first second third} value puts $x displays "first \{second \{third value\}\}" The _exists_ option mimics Tcl's _info exists_ command: set x {name value} pair exists x name -> 1 pair exists x name2 -> 0 The _set_ and _append_ options return the value of the node that has just been set, not the value of the variable. This would seem to be more in keeping with the intent of Tcl's _set_ and _append_ commands' return values than duplicating the exact behaviour: puts [pair set x {first second third} value] displays "value". An error is returned if a variable is passed to the _pair_ command which doesn't contain a well-formed paired Tcl list at any point on the way to the node specified by the _node_ argument: set x {name value thirdarg} pair get x name -> list must have an even number of elements If there are traces registered on the variable passed to the _pair_ command, they are triggered in the same manner as Tcl's _set_ and _append_ commands. Note that the _append_ option triggers only write triggers, not read triggers. Note that the _set_ and _append_ options both return the value of the node specified, and the _newValue_ argument is optional in both cases, making the _get_ option redundant. The _get_ command is included to improve readability. If the variable passed to _pair_ doesn't exist, it will be created if the option is 'set' or _append_; the _exists_ option will always return a _0_; the _get_ option will return an error. If a paired list contains multiple pairs with identical names, the pair occurring later in the list is targeted. This is specified to mimic the behaviour of _array set_: set x "name value1 name value2" pair get x name -> value2 array set arrX $x set arrX(name) -> value2 # Reference Implementation <http://sf.net/tracker/?func=detail&aid=491070&group\_id=10894&atid=310894> There should be a public C API for working with nested paired lists. The supplied reference code currently does not provide this. # Notes It would be nice to mimic Tcl 8.4's new _unset -nocomplain_ behaviour. # Side Effects Whether the result of the pair operation is successful, the underlying Tcl\_Obj that represents the list argument may have its internal representation invalidated or changed to that of a list. # Copyright This document has been placed in the public domain. |
Name change from tip/78.tip to tip/78.md.
|
| < | < | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 | # TIP 78: TEA 2.0 Definitions Author: Andreas Kupries <[email protected]> Author: Larry W. Virden <[email protected]> State: Draft Type: Informative Vote: Pending Created: 15-Dec-2001 Post-History: ----- # Abstract This document is an informational TIP providing definitions for commonly used terms \(like package, extension, core, distribution, etc.\) to make future communication among people in the community easier. It is recommended that future and past documents specifying details inside of the greater context of TEA refer to this document to ensure a consistent usage of terms. # Background This document is an adjunct to the [TIP <<vision>>]. _\(DKF - Is this meant to be a reference to [[34]](34.md)? Edit to such if so...\)_ To facilitate the specification and adoption of clearly defined interfaces to various activities and technologies it specifies a number of terms used by the community at large to create a greater unity and coherence in the usage of these terms. In other words, by creating generally accepted definitions for important terms the risk of misunderstanding each other is reduced. # Specification of Technical Terms This section specifies a number of important technical terms in alphabetical order. Terms used inside of a specification are highlighted. * Application > An entity implementing some functionality required by a _P/A User_ \(see section _Roles_\) to perform his work. Consists of one more files. May make use of _packages_ to implement its functionality. * Archive > Encapsulation of a _distribution_ in a single file. Well-known formats for archives are tar, gzipped tar, bzipped tar, and zip. * Binary generation > The process of wrapping up a built package into a binary _distribution_. See _building_ too. * Building > The process of _configuring_ and _transforming_ a source _distribution_ into a set of files which can be either immediately installed on the site which built them or wrapped into a binary _distribution_ for shipment to other sites. This also includes the execution of a test-suite coming with the package. * Bundle > A _distribution_ encapsulating more than one _package_. * Catalog > A catalog is a site providing an index of the packages. * Configuration > The process of customizing a source distribution for a particular architecture and/or site. A part of _Building_. * Conflict > Two or more packages are said to be in conflict if the usage of one of them excludes the usage of the others. > In a _strong conflict_ installing one of the packages disallows even the installation of the others. * Core > A shorthand for _Tcl core_. * Core distribution. > See _Tcl core distribution_. * Dependency > A relationship between packages. A package X is said dependent on another package Y if said package Y is required to allow X to work. > There are several types of dependencies: > \* Build-time dependency > > Y is required to allow X to be build. > \* Run-time dependency > > Y is required to allow the usage of an installed X. > \* Optional dependency > > Y can be used by X \(usually for improved performance\) but is not required for building or use. * Distribution > An encapsulation of one or more _packages_ for transport between places, machines, organizations, and people. Several types of distributions are possible, explained below. > 1. binary > > A binary distribution is in a state and format allowing the installation of the contained packages on a particular platform. > > It contains at least all the files > > \* implementing the functionality of the distributed packages and > > \* required to allow the package management of the Tcl core to handle the packages. > > A binary distribution usually contains just the files for a single architecture. This is not a explicit requirement however. In other words, a binary distribution is allowed to contain the files for several architectures. Such a binary distribution will be called a _fat binary distribution_. > > We distinguish between three sub-types: > > \* installable > > > This is the minimal binary distribution we spoke of before. > > \* auto-installable > > > Like _installable**, but additionally contains an application whose execution will perform all the steps which are necessary to install the contained packages at a site. The installation to add the packages to \(and thus the location of the installed packages\) can be freely chosen by the caller of the executable. > > \* auto-image > > > Like _auto-installable_, but the final location of the packages is hard-wired into the distribution. This means that a site using auto-images is restricted to one installation per architecture for which files are contained in the binary distribution. > > > Some of the existing archive formats restrict their contained distributions to this type. Examples of such archive formats are > > > \* RPM \(RedHat Package Manager\) > > > \* DEB \(DEBian Linux package format\) > > See [TIP 55] for the specification of a proposed layout for binary distributions. > 1. bundle > > A distribution which either contains the distributions of more than one package or a list of references to packages. The references are done by specifying the name and version of the packages contained in the bundle. > 1. buildable > > See _source_. > 1. compileable > > See _source_. > 1. raw > > A raw distribution is the most fundamental distribution. Its format is nearly completely unspecified. Its contents are straight from a source repository. The process of converting a raw distribution into a source distribution is called _Preparation_. > > Because of the unformatted nature of a raw distribution the commands for its conversion into a source distribution have to be part of it. This is the only part of a raw distribution which can and has to be specified. > > Example: The execution of _autoconf_ to generate a _configure_ script from its _configure.in_ file can be a single step in a complex preparation. > 1. source > > A source distribution is in a format and state where tools can be used to build its contents. > > The format needs further specification but for now we can assume that it is governed by the current TEA specification. > > Alternate name for this type of distribution are _compileable_ and _buildable_. * Distribution repository > See _repository_ * Extension > Alternate name for a _package_, generally used for packages requiring compilation to become functional. > This term is _deprecated_. * Installation > A special type of _distribution repository, binary_ \(see _repository_\) containing all _packages_ which were installed on a site. A site may host several installations differing in version and/or configuration of Tcl, and/or the platform Tcl was built for, etc. > Currently difficult to do but in the future it should made be possible for an installation to refer and use another installation, provided both are configured identically. This allows a site to build a hierarchy of installations from the most general containing the common packages down to installations associated with one or more _P/A Developers_. * Installing > The process of unpacking a binary distribution and adding the contained packages to an _installation_. The latter may include moving files to their proper places. > Also the process of adding a built package to an _installation_. * Manifest > A file detailing the files making up a particular package. * Package > A collection of files providing additional functionality to a user of a Tcl interpreter when loaded into said interpreter. > Some files in a package implement the provided functionality whereas other files contain meta-information required by the package management of Tcl to be able to use the package. * Preparation > The process of converting a raw _distribution_ into a source _distribution_ suitable as input to _building_. This includes actions like: > \* Retrieval of sources from a source repository > \* Creating a _configure_ file from its _configure.in_. > \* Creating the distributed documentation from internal sources. > \* Removal of internal files containing notes, scratch info and the like. > \* Inserting version information into files. > \* ... > The tool _makedist_ \(which I wrote\) is in my mind when thinking about this step. * Raw retrieval > The process of retrieving a raw _distribution_ from a _source repository_. * Repository > General term with two possible meanings. > 1. A collection of _archives_. The exact term for this type of repository is "distribution repository". > > If a distribution repository is restricted to one type of distributions this type can be added to the term as further specification of the type of repository. Thus > > \* _distribution repository, binary_, or > > \* _distribution repository, source_. > 2. A collection of directories, developer files and control files containing version control information. The exact term for this type of repository is _source repository_. > > A repository can either be internal to an organization or public. * Source repository > See _repository_ * Tcl core > The most fundamental part in the Tcl world; the interpreter engine and the builtin commands coming with it. These are all commands and procedures reported by _info commands_ for a _tclsh_ which was started with an empty _.tclshrc_ file and after sourcing all _.tcl_ files in the directory returned by _info library_. * Tcl core distribution > The most fundamental distribution there is. Contains the _Tcl core_ and a number of packages. # Roles The terms in the preceding section specified both passive data structures and actions upon them. This section specifies the possible actors, i.e. entities which perform one or more of these actions. To make the specification easier, related actions are grouped into roles of behavior. The mapping from roles to actual actors, i.e. people and organizations is n:m. On other words, one actor may have several roles, either at once or changing over time and one role can be held by several distinct actors. Examples are given at the end of this section. 1. Catalog manager > A catalog manager handles one or more catalogs. He is responsible for > \* the final name arbitration for packages with conflicting names > \* and the categorization of the packages indexed by the catalog. 1. P/A Builder > A package and/or application builder is a person and/or organization > \* who retrieves raw distributions from source repositories and \(in a sequence of several steps\) generates binary distributions from them. > \* or who retrieves source distributions from distribution repositories and \(in a sequence of several steps\) generates binary distributions from them. > \* uploads the generated binary distributions into one or more distribution repositories. > \* uploads the generated source distributions into one or more distribution repositories. > The intermediate steps performed by a builder are _Preparation_, _Building_, and _Binary generation_. > If _System administrator_ and _P/A Builder_ coordinate with each other it is also possible to install a package directly from the built package. > _NOTE:_ Think about splitting P/A Builder into two roles; one for the preparation of source _distributions_ and a second role for the generation of binary _distributions_. TODO Find some nice names for the split roles. 1. P/A Developer > A developer is a _P/A User_ whose tasks include the creation of new packages and/or applications. A workspace contains the raw sources of these new packages and applications. For posterity and version control it is kept synchronized with one or more _source repositories_. > During development, at least one installation has to be accessible, containing the initial packages, the new packages and the applications built upon the packages. 1. P/A User > A person or organization which uses Tcl based tools but does not develop new code. Its workspace contains the files required for the tasks at hand. > The border between the roles of P/A Developer and P/A User blurs if the tool being used allows one to customize/program/extend it in Tcl. 1. Repository manager > This role handles the management of all types of _repositories_. This role is not part of the development process _per se_ and has no direct actions for with regards to distributions, packages, sources, etc. > Repository managers are responsible for keeping the system up and running, doing adequate backups, supporting mirrors, providing browsing and download capabilities, providing confidence that updates to items in the repository are being done by the approved person or persons, etc. > The role is related to _System administrator_, but not the same. It was split out of that role because a _System-Administrator_ is usually internal to an organization whereas a repository and its management can be provided by an entity external to the organization. 1. System administrator > A system administrator manages > \* one or more _installations_ of the Tcl core and additional packages. Each installation may be configured differently \(Tcl version, installed packages, platform, ...\). > \* Installed packages are taken either from a _distribution repository_ or directly from a built package. The latter has to be done in coordination with a _P/A Builder_. > Her responsibilities include > \* the creation of empty installations, > \* the destruction of installations, > \* the addition and removal of packages to/from an existing installation. The three P/A roles are central to the development process and bound together in a tight loop of information flowing between them. The other three roles handle the support structure without which the other roles would be unable to communicate and collaborate. ![](../assets/78pa_cycle.gif) Examples: * Larry Virden is _System-Administrator_, _P/A Builder_ and _P/A User_ for his organization. * I \(the author of this TIP\) am all roles, on my system at home. * ActiveState is _Repository Manager_ for the Perl community and plans to become one for the Tcl community. * SourceForge is a combination of _Repository Manager_ and _Catalog Manager_. * Most people with a windows machine at home are _System-Administration_ and _P/A User_ for this machine. # Visual Representation The following drawings are a visual adjunct to the terms in the last sections to aid in the understanding of the terms and their relations. Legend: * Blue rounded boxes - Areas of responsibility for roles. The responsible role is written in gold text inside of the box. * White rounded boxes with a black border - Data, like packages, distributions, etc. * White boxes with a red border - Actions on data. ![Roles, Data and Actions](../assets/78tea_terms_relations_1.gif) ![Relationships Between Data Entities](../assets/78tea_terms_relations_2.gif) # Copyright This document has been placed in the public domain. |
Name change from tip/79.tip to tip/79.md.
|
| < | < | | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 79: Add Deletion Callback to Tcl_CreateObjTrace Author: Kevin Kenny <[email protected]> State: Final Type: Project Vote: Done Created: 03-Jan-2002 Post-History: Discussions-To: news:comp.lang.tcl Keywords: trace,Tcl_Obj Tcl-Version: 8.4 ----- # Abstract This document is a correction to the _Tcl\_CreateObjTrace_ API from [[32]](32.md). It addresses a deficiency that the API provides no deletion callback for its client data. # Rationale In developing a reference implementation for the changes described in [[32]](32.md), the author of this TIP discovered an anomaly in the proposed API for _Tcl\_CreateObjTrace._ While the function accepts a _ClientData_ parameter, it provides no deletion callback for the client data, making it difficult to clean up the client data if _Tcl\_DeleteTrace_ is called from a point in the code where the client data is not readily available. \(The usual pattern in the Tcl library is to provide a deletion callback wherever client data is passed to the Tcl interpreter; _Tcl\_CreateObjCommand_ is an example. # Specification The _Tcl\_CreateObjTrace_ function proposed in [[32]](32.md) shall be changed to the following: Tcl_Trace Tcl_CreateObjTrace ( Tcl_Interp* interp, int level, int flags, Tcl_CmdObjTraceProc* objProc, ClientData clientData, Tcl_CmdObjTraceDeleteProc* deleteProc ); The _Tcl\_CreateObjTrace_ function adds a trace to the Tcl evaluator. The _interp_ argument is the Tcl interpreter for which tracing is being requested. The _level_ argument is the maximum depth of recursive calls; when the execution depth of the interpreter exceeds this number, the trace callback does not execute. The _objProc_ argument is the callback procedure to execute each time a Tcl command is evaluated; it is expected to have arguments and result type that match _Tcl\_CmdObjTraceProc_ below. The _clientData_ argument is client data to pass to the _objProc_ callback. The _deleteProc_ argument specifies a function to call when the trace is removed by a call to _Tcl\_DeleteTrace._ This parameter may be a null pointer if no deletion callback is desired. Finally, the _flags_ argument gives flags that control the tracing. Initially, the only flag supported will be _TCL\_ALLOW\_INLINE\_COMPILE_. If this flag is set, the bytecode compiler is permitted to compile in-line code for the Tcl built-in commands; any command that has been compiled in-line will not be traced. The trace token returned from _Tcl\_CreateObjTrace_ may be passed as a parameter to _Tcl\_DeleteTrace_, which arranges to cancel the tracing. If a non-empty _deleteProc_ argument was supplied to _Tcl\_CreateObjTrace_, it is called at this time. After _Tcl\_DeleteTrace_ returns, no further calls to the trace procedure will be made, and the trace token must not be used further in the calling program. The _Tcl\_CmdObjTraceProc_ will have the following type signature. typedef int Tcl_CmdObjTraceProc( ClientData clientData, Tcl_Interp* interp, int level, CONST char* command, Tcl_Command commandInfo, int objc, Tcl_Obj *CONST objv[] ); The _clientData_ parameter is the client data that was passed to _Tcl\_CreateObjTrace_. The _interp_ parameter designates a Tcl interpreter. The _level_ parameter specifies the execution level. The _command_ parameter gives the raw UTF-8 text of the command being evaluated, before any substitutions have been performed. The _commandInfo_ parameter is an opaque _Tcl\_Command_ object that gives information about the command. The _objc_ and _objv_ parameters are the command name and parameter vector after substitution. The trace procedure is expected to return a standard Tcl status return. If it returns _TCL\_OK_, the command is evaluated normally. If it returns _TCL\_ERROR_, evaluation of the command does not take place. The interpreter result is expected to contain an error message. If it returns any other status, such as _TCL\_BREAK_, _TCL\_CONTINUE_ or _TCL\_RETURN_, it is treated as if the command had done so. The _Tcl\_CmdObjTraceDeleteProc_ will have the following type signature. typedef void Tcl_CmdObjTraceDeleteProc( ClientData clientData ); The _clientData_ parameter is the client data that was originally passed into _Tcl\_CreateObjTrace_. # Copyright Copyright © 2002 by Kevin B. Kenny. Distribution in whole or part, with or without annotations, is unlimited. |
Name change from tip/8.tip to tip/8.md.
|
| < | < | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 8: Add Winico support to the wm command on windows Author: Vince Darley <[email protected]> State: Final Type: Project Tcl-Version: 8.4.0 Vote: Done Created: 06-Nov-2000 Post-History: ----- # Abstract Add to _wm_ the ability to do the windows-titlebar-icon manipulation that the Winico extension currently provides, without the bugs noted in that extension. # Proposal Modify _wm_ on Windows only to allow an optional _-default_ argument. wm iconbitmap .winpath ?-default? filename And to allow a file which is of valid windows-icon format to be interpreted as such. Any file which is not correctly interpreted as an icon will be handled as before, by the _bitmap_ code \(which will generally either do nothing, or throw an error, thus maintaining backwards compatibility\). The _-default_ argument, if given, will change not the icon of the .winpath given, but rather the default icon for all windows in the current application for which no specific icon as been set. An implementation already exists, which fixes the basic "wrapper window" problems and which has the above syntax. The issues surrounding reference counting of icons in use has also been addressed in this patch so that icons no longer in use are released \(the Winico patch required manual deletion of icons\). This reference implementation is available from ftp://ftp.ucsd.edu/pub/alpha/tcl/tkWinWm.diff \(documentation has been separately patched, and can also be made available\). # Rationale There have been many requests on news:comp.lang.tcl for this ability in the Tk core, and several bug reports filed against Winico, and this ability has been placed on the Tk 8.4 roadmap. <http://purl.org/tcl/home/software/tcltk/roadmap.tml> The choice of _wm iconbitmap_ is suggested, because _wm iconbitmap_ currently doesn't appear to do anything on Windows, yet is the obvious choice for the user trying to set the window's icon \(e.g. many posts on news:comp.lang.tcl are actually asking why _wm iconbitmap_ doesn't do anything\). In the future we may wish to extend _wm iconbitmap_ on all platforms so that other image types can be accepted \(e.g. .gif, .png\). This proposal extends naturally to allow such future work. The primary changes required will be icon<->image conversion routines. # Alternatives Fix the core so that Winico can work properly as an extension. My implementation as shown that this would require a couple of patches, and also the exporting of an additional obscure function into Tk's stub table \(a function which would ensure that Tk's window manager is completely initialised\). It would also not help the users posting to news:comp.lang.tcl asking "why doesn't wm iconbitmap do anything?" # Objections _This is platform specific and should go in an extension_ See _Alternatives_ above, also see the _future suggestion_ above in which this kind of code can be usefully extended in a cross-platform way. _The -default flag is weird, and it means we ignore the window name_ I agree, but please suggest a better alternative rather than just moaning. The command with the -default flag is in my opinion more useful than the command without \(for example it makes sure that Tk's built-in dialogs have the icon of your application\). An alternative might be to use _wm iconbitmap -default filename_, but that involves more significant modifications of the semantics of _wm_. It might, however, be a good idea. _wm iconbitmap will still do nothing when given a bitmap_ Yes, but there's that backwards compatibility issue. This should be properly documented with pointers to the use of valid icon file formats. When or if proper support is added to Tk for .gif, .png or even Tk images as icons, this bug can be fixed. The purpose of this TIP is not to fix that bug, but to provide a better solution. # Copyright This document has been placed in the public domain. |
Name change from tip/80.tip to tip/80.md.
|
| < | < | | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | < | > | | | | | | | | | | < > | < > | | < > | | < > | | < > | | | | | | | | | < > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | < > | | | | < > | | | | | | | | | | | | | | | | | | | < > | | | | | | | | | | | | | | | | | | | | | | | | | | | | < < > > | | | | | | | | < > | | | | | | | | < > | | | | | | | | | | | < > | | < > | | | | | | | | | | | | | | | | < > | | | | | < > | < > | | < > | | | | | | | | | | | | | | | | | | | | | | | < > | | | | < > | | | | < > | | | | | | < > | < > | | | | | < > | | | | | | < > | < < > > | | | | | | | | | | | | | | | | | | | | < > | | | | | < < < > > > | | | | | | | | | | | | < > | < > | | | | | < > | | | | | < > | < < < < < < < < < < < < | < < < < < < < < < < > | | < < < > | < < < < < < | < < < < < < < < > > | < < < < < < < < < > > > > | < < | < < < > > > | | < < > | < > > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | | | | | | | < > | | | | | < < > > | < > | | < > | | | | | < < > > | < > | | < > | | | | | | < > | < > | < > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 | # TIP 80: Additional Options for 'lsearch' Author: Tom Wilkason <[email protected]> Author: Tom Wilkason <[email protected]> State: Final Type: Project Vote: Done Created: 02-Jan-2002 Post-History: Discussions-To: news:comp.lang.tcl Tcl-Version: 8.4 ----- # Abstract This TIP proposes additional options for the _lsearch_ command to return and work with all matching items in the return rather than the first matching item. Additional options are also added. # Rationale The _lsearch_ function works well for finding the first item in a list that matches a pattern. However it is often useful to find all of the items in the list that match a pattern. This TIP proposes adding options to return the entire list of matches. With this capability, additional options are proposed to return the data rather than the indices \(since you often want to work the the data anyway\), and to add an option to return the logical exclusion of the matching items \(i.e. those that don't match the search pattern\). # Specification I propose the following options be added to _lsearch_: Option: _-start index_ > Initiates the list search starting at _index_, which can be any valid list index \(such as 0 , end , end-1 ...\) Option: _-all_ > Returns a list of all indices that match the search condition \(rather than the first one\). The indices are returned low to high order. For a no match condition, a \{\} \(empty list\) is returned. If the the _-all_ or _-inline_ switches are not specified, a -1 is returned for a no match condition just as is done now. Option: _-inline_ > Returns a single item \(or a list of items for _-all_\) of the data that matches the search condition rather than the index \(or indices\). An empty result or empty list \(_-all_\) is returned for a no match condition. The data is returned in original list order. This option is useful when you want to iterate over the returned data anyway. e.g. foreach item [lsearch -all -inline -glob $someList *stuff] { # deal with item } Option: _-not_ > Negates the sense of the search condition \(i.e. what doesn't match\). When used with the _-inline_ or _-all_ options, the return set will be the items that do match. If all items match then a \{\} is returned. Without the _-all_ option, the first item in the list that does not match will be returned. These can be combined as needed and yield some powerful capabilities when iterating over sub-lists \(esp. with the new _lset_ command\). # Reference Implementation Changes to the _Tcl\_LsearchObjCmd_ command in _generic/tclCmdIL.c_ are needed along with documentation and test code. The changes to the 8.4 head version of _tclCmdIL.c_ are available below. /* *---------------------------------------------------------------------- * * Tcl_LsearchObjCmd -- * * This procedure is invoked to process the "lsearch" Tcl command. * See the user documentation for details on what it does. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ int Tcl_LsearchObjCmd(clientData, interp, objc, objv) ClientData clientData; /* Not used. */ Tcl_Interp *interp; /* Current interpreter. */ int objc; /* Number of arguments. */ Tcl_Obj *CONST objv[]; /* Argument values. */ { char *bytes, *patternBytes; int i, match, mode, index, result, listc, length, elemLen; int useStart=-1, offset, allData=0, returnInline=0; int dataType, isIncreasing, lower, upper, patInt, objInt, notMatch=0; double patDouble, objDouble; Tcl_Obj *patObj, **listv, *listPtr, *startPtr = NULL; static CONST char *options[] = { "-all", "-ascii", "-decreasing", "-dictionary", "-exact", "-glob", "-increasing", "-inline", "-integer", "-not", "-real", "-regexp", "-sorted", "-start", NULL }; enum options { LSEARCH_ALL, LSEARCH_ASCII, LSEARCH_DECREASING, LSEARCH_DICTIONARY, LSEARCH_EXACT, LSEARCH_GLOB, LSEARCH_INCREASING, LSEARCH_INLINE, LSEARCH_INTEGER, LSEARCH_NOT, LSEARCH_REAL, LSEARCH_REGEXP, LSEARCH_SORTED, LSEARCH_START }; enum datatypes { ASCII, DICTIONARY, INTEGER, REAL }; enum modes { EXACT, GLOB, REGEXP, SORTED }; mode = GLOB; dataType = ASCII; isIncreasing = 1; /* Note: This counts options as possible list|patterns */ if (objc < 3) { Tcl_WrongNumArgs(interp, 1, objv, "?options? list pattern"); return TCL_ERROR; } for (i = 1; i < objc-2; i++) { if (Tcl_GetIndexFromObj(interp, objv[i], options, "option", 0, &index) != TCL_OK) { return TCL_ERROR; } switch ((enum options) index) { case LSEARCH_ASCII: /* -ascii */ dataType = ASCII; break; case LSEARCH_NOT: /* -not */ notMatch = 1; break; case LSEARCH_ALL: /* -all */ allData = 1; listPtr = Tcl_NewListObj(0, (Tcl_Obj **) NULL); break; case LSEARCH_INLINE: /* -inline */ returnInline = 1; break; case LSEARCH_START: /* -start index */ useStart = ++i; /* Use next arg as offset index */ if (objc-i < 2) { Tcl_SetResult(interp, "missing argument to -start option", TCL_STATIC); } break; case LSEARCH_DECREASING: /* -decreasing */ isIncreasing = 0; break; case LSEARCH_DICTIONARY: /* -dictionary */ dataType = DICTIONARY; break; case LSEARCH_EXACT: /* -exact */ mode = EXACT; break; case LSEARCH_INCREASING: /* -increasing */ isIncreasing = 1; break; case LSEARCH_INTEGER: /* -integer */ dataType = INTEGER; break; case LSEARCH_GLOB: /* -glob */ mode = GLOB; break; case LSEARCH_REAL: /* -real */ dataType = REAL; break; case LSEARCH_REGEXP: /* -regexp */ mode = REGEXP; break; case LSEARCH_SORTED: /* -sorted */ mode = SORTED; break; } } /* * -start option processing: * Ensure we get a unique copy of command line arg for start index */ if (useStart > 0) { startPtr = Tcl_DuplicateObj(objv[useStart]); } /* * Make sure the list argument is a list object and get its length and * a pointer to its array of element pointers. */ result = Tcl_ListObjGetInline(interp, objv[objc - 2], &listc, &listv); if (result != TCL_OK) { return result; } /* * Retrieve user specified start offset. */ if (useStart > 0) { result = TclGetIntForIndex(interp, startPtr, /*end*/ listc-1, &offset); Tcl_DecrRefCount(startPtr); /* free unneeded obj */ if (result != TCL_OK) { return result; } else if (offset < 0) { offset = 0; } } else { offset = 0; } /* * Process the pattern */ patObj = objv[objc - 1]; patternBytes = NULL; if ((enum modes) mode == EXACT || (enum modes) mode == SORTED) { switch ((enum datatypes) dataType) { case ASCII: case DICTIONARY: patternBytes = Tcl_GetStringFromObj(patObj, &length); break; case INTEGER: result = Tcl_GetIntFromObj(interp, patObj, &patInt); if (result != TCL_OK) { return result; } break; case REAL: result = Tcl_GetDoubleFromObj(interp, patObj, &patDouble); if (result != TCL_OK) { return result; } break; } } else { patternBytes = Tcl_GetStringFromObj(patObj, &length); } /* * Set default index value to -1, indicating failure; if we find the * item in the course of our search, index will be set to the correct * value. */ index = -1; match = 0; if ((enum modes) mode == SORTED && allData == FALSE) { /* * If the data is sorted, we can do a more intelligent search. * Note that there is no point in being smart when -all was * specified; in that case, we have to look at all items anyway. */ lower = offset-1 /*-1*/; upper = listc; while (lower + 1 != upper) { i = (lower + upper)/2; switch ((enum datatypes) dataType) { case ASCII: { bytes = Tcl_GetString(listv[i]); match = strcmp(patternBytes, bytes); break; } case DICTIONARY: { bytes = Tcl_GetString(listv[i]); match = DictionaryCompare(patternBytes, bytes); break; } case INTEGER: { result = Tcl_GetIntFromObj(interp, listv[i], &objInt); if (result != TCL_OK) { return result; } if (patInt == objInt) { match = 0; } else if (patInt < objInt) { match = -1; } else { match = 1; } break; } case REAL: { result = Tcl_GetDoubleFromObj(interp, listv[i], &objDouble); if (result != TCL_OK) { return result; } if (patDouble == objDouble) { match = 0; } else if (patDouble < objDouble) { match = -1; } else { match = 1; } break; } } if (match == 0) { /* * Normally, binary search is written to stop when it * finds a match. If there are duplicates of an element in * the list, our first match might not be the first occurance. * Consider: 0 0 0 1 1 1 2 2 2 * To maintain consistancy with standard lsearch semantics, * we must find the leftmost occurance of the pattern in the * list. Thus we don't just stop searching here. This * variation means that a search always makes log n * comparisons (normal binary search might "get lucky" with * an early comparison). */ index = i; upper = i; } else if (match > 0) { if (isIncreasing) { lower = i; } else { upper = i; } } else { if (isIncreasing) { upper = i; } else { lower = i; } } } } else { for (i = offset; i < listc; i++) { match = 0; switch ((enum modes) mode) { case SORTED: case EXACT: { switch ((enum datatypes) dataType) { case ASCII: { bytes = Tcl_GetStringFromObj(listv[i], &elemLen); if (length == elemLen) { match = (memcmp(bytes, patternBytes, (size_t) length) == 0); } break; } case DICTIONARY: { bytes = Tcl_GetString(listv[i]); match = (DictionaryCompare(bytes, patternBytes) == 0); break; } case INTEGER: { result = Tcl_GetIntFromObj(interp, listv[i], &objInt); if (result != TCL_OK) { return result; } match = (objInt == patInt); break; } case REAL: { result = Tcl_GetDoubleFromObj(interp, listv[i], &objDouble); if (result != TCL_OK) { return result; } match = (objDouble == patDouble); break; } } break; } case GLOB: { match = Tcl_StringMatch(Tcl_GetString(listv[i]), patternBytes); break; } case REGEXP: { match = Tcl_RegExpMatchObj(interp, listv[i], patObj); if (match < 0) { return TCL_ERROR; } break; } } /* Invert match condition for -not */ if (notMatch) { match = (match != 0 ? 0 : 1); } /* Process the possible match for this element */ if (match != 0) { if (allData) { if (returnInline) { /* Append data */ Tcl_ListObjAppendElement(interp, listPtr,listv[i]); } else { /* Append index */ Tcl_ListObjAppendElement(interp, listPtr,Tcl_NewIntObj(i)); } } else { index = i; break; } } } } /* * Return either a list (-all) or a single element */ if (allData) { Tcl_SetObjResult(interp,listPtr); } else { if (returnInline) { if (index < 0) { /* Return a null */ Tcl_SetObjResult(interp,Tcl_NewObj()); } else { /* Return one datum */ Tcl_SetObjResult(interp,listv[index]); } } else { Tcl_SetIntObj(Tcl_GetObjResult(interp), index); } } return TCL_OK; } # Notes The changes to _lsearch_ are entirely backward compatible and do no change the behaviour or performance of the command for existing options. Moreover, these changes should not impact any of the other list changes in [[22]](22.md), [[33]](33.md) or [[45]](45.md). # Copyright This document has been placed in the public domain. # Appendix The benchmarks below denote the expected speed increase of using the new options vs. tcl only implementations. Your mileage may vary. ## # performs a lsearch -all -inline -glob search # proc lsearch_dataGLOB {listData pattern} { set result [list] foreach item $listData { if {[string match $pattern $item]} { lappend result $item } } return $result } ## # performs a lsearch -all -inline -regexp search # proc lsearch_dataRE {listData pattern} { set result [list] foreach item $listData { if {[regexp $pattern $item]} { lappend result $item } } return $result } ## # performs a lsearch -all -glob search # proc lsearch_allGLOB {listData pattern} { set result [list] set count 0 foreach item $listData { if {[string match $pattern $item]} { lappend result $count } incr count } return $result } # Build a 2K list of data catch {unset LIST} time {lappend LIST someStuff} 1000 time {lappend LIST otherStuff} 1000 # Case with all data matching in a 2K list 2.8x speedup puts "#C implementation [time {lsearch -glob -all -inline $LIST *Stuff} 100]" #=> C implementation 3766 microseconds per iteration puts "#tcl implementation [time {lsearch_dataGLOB $LIST *Stuff} 100]" #=> tcl implementation 10815 microseconds per iteration # Case with all data matching but returning indicies 3X speed up puts "#C implementation [time {lsearch -glob -all $LIST *Stuff} 100]" #=> C implementation 4305 microseconds per iteration puts "#tcl implementation [time {lsearch_allGLOB $LIST *Stuff} 100]" #=> tcl implementation 13277 microseconds per iteration # Case with no matching data 8X speed up puts "#C implementation [time {lsearch -glob -all -inline $LIST none*} 100]" #=> C implementation 646 microseconds per iteration puts "#tcl implementation [time {lsearch_dataGLOB $LIST none*} 100]" #=> tcl implementation 5354 microseconds per iteration # Repeat with RE, note more time spent in RE engine 2X speedup puts "#C implementation [time {lsearch -regexp -all -inline $LIST Stuff} 100]" #=> C implementation 35260 microseconds per iteration puts "#tcl implementation [time {lsearch_dataRE $LIST Stuff} 100]" #=> tcl implementation 62292 microseconds per iteration # Case with no matching data 2X speedup puts "#C implementation [time {lsearch -regexp -all -inline $LIST none*} 100]" #=> C implementation 14815 microseconds per iteration puts "#tcl implementation [time {lsearch_dataRE $LIST none} 100]" #=> tcl implementation 30553 microseconds per iteration |
Name change from tip/81.tip to tip/81.md.
|
| < | < | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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 | # TIP 81: [incr Tcl] Functional Areas for Maintainer Assignments Author: Donal K. Fellows <[email protected]> State: Withdrawn Type: Process Vote: Pending Created: 07-Jan-2002 Post-History: ----- # Abstract This document proposes a division of [incr Tcl]'s source code into functional areas so that each area may be assigned to one or more maintainers. # Background In order for [incr Tcl] to be adopted by the Tcl Core Team \(see [[50]](50.md)\), it must be managed by the processes already established for handling source \(see [[0]](0.md) and [[16]](16.md) for details and rationale.\) # Functional Areas [incr Tcl] shall be divided into the following 8 functional units \(the seventh is the obsolete parts of the source tree, and the eighth is the shared part of the source tree\), each to be assigned one or more maintainers: 1. _Objects_ - generic/itcl\_bicmds.c, generic/itcl\_class.c, generic/itcl\_methods.c, generic/itcl\_objects.c, generic/itcl\_parse.c, doc/body.n, doc/class.n, doc/configbody.n, tests/basic.test, tests/body.test, tests/info.test, tests/inherit.test, tests/interp.test, tests/methods.test, tests/protection.test, 2. _Other Commands_ - generic/itcl\_cmds.c, generic/itcl\_ensemble.c, doc/code.n, doc/delete.n, doc/ensemble.n, doc/find.n, doc/local.n, doc/scope.n, tests/chain.test, tests/delete.test, tests/ensemble.test, tests/import.test, tests/local.test, tests/namespace.test, tests/scope.test 3. _Mac Build\+Support_ - mac/tclMacAppInit.c, mac/MW\_ItclHeader.pch, mac/pkgIndex.tcl, mac/itclMacApplication.r, mac/itclMacLibrary.r, mac/itclMacResource.r, mac/itclMacTclCode.r, mac/itclStaticApplication.r 4. _Unix Build\+Support_ - unix/tclAppInit.c, configure.in _\(to move to unix/configure.in\)_, aclocal.m4 _\(to move to unix/aclocal.m4 and gain pieces the poorly-named Itcl tcl.m4\)_, Makefile.in _\(to move to unix/Makefile.in\)_, itclConfig.sh.in _\(to move to unix/itclConfig.sh.in\)_, pkgIndex.tcl.in _\(to move to unix/pkgIndex.tcl.in\)_ 5. _Windows Build\+Support_ - win/dllEntryPoint.c, win/makefile.bc, win/makefile.vc, win/rc/itcl.rc 6. _Other_ - generic/itcl\_util.c, generic/itcl\_linkage.c, doc/itclsh.1, library/itcl.tcl, tests/mkindex.itcl, tests/mkindex.test, tests/tclIndex # Obsolete Files These files are all obsolete in one way or another, and will be removed as part of the migration process. They are listed here for completeness only. * generic/itcl\_obsolete.c, generic/itcl\_migrate.c, doc/man.macros, doc/itcl\_class.n, doc/itcl\_info.n tests/defs, tests/old/AAA.test, tests/old/Bar.tcl, tests/old/BarFoo.tcl, tests/old/Baz.tcl, tests/old/Foo.tcl, tests/old/FooBar.tcl, |
︙ | ︙ | |||
128 129 130 131 132 133 134 | tests/old/toasters/Hazard.tcl, tests/old/toasters/Outlet.tcl, tests/old/toasters/SmartToaster.tcl, tests/old/toasters/Toaster.tcl, tests/old/toasters/tclIndex, tests/old/toasters/usualway.tcl | | | | | | | | > | 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 | tests/old/toasters/Hazard.tcl, tests/old/toasters/Outlet.tcl, tests/old/toasters/SmartToaster.tcl, tests/old/toasters/Toaster.tcl, tests/old/toasters/tclIndex, tests/old/toasters/usualway.tcl # Shared Files The following files are shared by all of [incr Tcl]. Any maintainer may modify them as necessary to complete changes they are making to their portion of [incr Tcl]. Some of the following files define [incr Tcl]'s API and should be changed only in accordance with TCT approval. * generic/itcl.h, generic/itclInt.h, generic/itcl.decls, generic/itclInt.decls, doc/itcl.n, doc/itclvars.n, tests/all, tests/all.tcl # Generated Files The following files are generated, so they don't need maintainers. * generic/itclDecls.h, generic/itclIntDecls.h, generic/itclStubInit.c, generic/itclStubLib.c, configure _\(moves to unix/configure, trailing configure.in\)_ # Copyright This document has been placed in the public domain. |
Name change from tip/82.tip to tip/82.md.
|
| < | < | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 82: Add -offrelief Option to Checkbutton and Radiobutton Author: D. Richard Hipp <[email protected]> State: Final Type: Project Vote: Done Created: 10-Jan-2002 Post-History: Tcl-Version: 8.4 ----- # Abstract This TIP proposes adding option _-offrelief_ to the checkbutton and radiobutton widgets to specify the relief of the widget when _-indicatoron_ is off and the state of the button is off. This feature is needed to support the use of checkbutton and radiobutton widgets on toolbars. # Rationale The checkbutton and radiobutton widgets both support the _-overrelief_ option which is suppose to provide the capability to change the relief of the widget on mouse-over. The _-overrelief_ option is not used by the underlying C code. The value of _-overrelief_ is used only by the script bindings to change the _-relief_ option in response to _<Enter>_ and _<Leave>_ events. But with the checkbutton and radiobutton widgets, the value of _-relief_ is ignored when _-indicatoron_ is turned off. Hence, _-overrelief_ has no effect when _-indicatoron_ is off. An example of the effect we would like to achieve is the Bold/Italic/Underline and text justification toolbar buttons on word processors. The Bold/Italic/Underline toolbar buttons are most naturally implemented using Tk checkbuttons and the text justification toolbar buttons are most naturally implemented using Tk radiobuttons. The buttons are configured to be flat most of the time \(_-relief_ flat\) but raise up on mouseover \(_-overrelief_ raised\). Toolbar buttons do not show indicators \(_-indicatoron_ off\). This last configuration option is the crux of the problem since when _-indicatoron_ is off, the relief of the button is hard-coded to be raised when the button is on and sunken when the button is off. In the current implementation, there is no way to get the off-relief to be flat, and hence there is no way to achieve the customary look for these common toolbar buttons. # Proposed Enhancement This TIP proposes to modify the checkbutton and radiobutton widgets to support a _-offrelief_ option. _-offrelief_ will take any of the usual relief values. The default value will be _raised_. The _-offrelief_ option determines the relief of the widget when _-indicatoron_ option is off and the button itself is off. The default bindings for checkbuttons and radiobuttons will also need to be changed so that they copy the value of _-overrelief_ into _-offrelief_ instead of into _-relief_ when the value of _-indicatoron_ is false. When _-indicatoron_ is off and the button itself is on, the relief continues to be hard-coded to sunken. For symmetry, we might consider adding another _-onrelief_ option to cover this case. But it is difficult to imagine ever wanting to change the value of _-onrelief_ so it has been omitted from this TIP. If there as strong desire to have _-onrelief_, it can be added later. # Alternative Proposals A simpler solution would be to change the _-indicatoron_ option so that it causes the off-relief to come from the _-relief_ option instead of using a hard-coded _raised_ relief. That approach is conceptually simpler, but it breaks backwards compatibility and so must be rejected. Another possibility is to modify _-indicatoron_ so that it takes a third value \(other than _on_ or _off_\) where the third value works like _off_ but takes the off-relief from the _-relief_ option instead of always using _raised_. But this second idea seems more contrived and makes it more difficult to define an alternative on-relief value with a later modification. # Copyright This document has been placed in the public domain. |
Name change from tip/83.tip to tip/83.md.
|
| < | < | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | < > | | | | | | < > | | | | | | < > | > | > > | > > > | < < < < < < | | | | | | | | | | | < > | | | | | | | | < > | | | | | | | < > | | | | | | < | > | | | | | < > | < | > | | | | | < > | | | | | | | | | | | | | | | < > | | < > | | | | | | | | | | | | | | | | | | | | < > | | | | < | > | | | > | 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 | # TIP 83: Augment Tcl_EvalFile with Tcl_EvalChannel and Tcl_EvalUrl Author: Marian Szczepkowski <[email protected]> Author: <[email protected]> State: Withdrawn Type: Project Vote: Pending Created: 24-Jan-2002 Post-History: Tcl-Version: 8.5 ----- # Abstract This TIP adds the ability to load Tcl files directly from URLs to the core, together with a basic mechanism to simply evaluate a stream of characters from a channel. # Proposal I propose to split the _Tcl\_EvalFile_ function into two components to enable the [source] command to use URL's to obtain source material. This will mean splitting _Tcl\_EvalFile_ into _Tcl\_EvalFile_ and _Tcl\_EvalChannel_ which are the two logical entities. Maintaining _Tcl\_EvalFile_ will preserve backward compatability. Creating _Tcl\_EvalChannel_ will provide generic functionality for future use. Adding _Tcl\_EvalUrl_ will enable handling standard URL format strings. This would enable this [source <http://anywhere.com/file.tcl]> to be used. Code will also need to be added to _Tcl\_SourceObjCmd_ to select functionality requested. # Pro. In a corporate environment where scripts are subject to change but the interface is not, this allows scripts to be stored remotely on a central server. This also allows Tcl to interwork in a networked environment. # Con. Security!!!! This may mean in the long run adding a signing layer, but don't use it if you don't want to. # Sample I figure it looking something like this. Snipped from 8.3 source. # Tcl\_SourceObjCmd int Tcl_SourceObjCmd(dummy, interp, objc, objv) ClientData dummy; /* Not used. */ Tcl_Interp *interp; /* Current interpreter. */ int objc; /* Number of arguments. */ Tcl_Obj *CONST objv[]; /* Argument objects. */ { char *bytes; int result; if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "fileName"); return TCL_ERROR; } bytes = Tcl_GetString(objv[1]); if (strstr(ptr,"://")) { result = Tcl_EvalFile(interp, bytes); } else { result = Tcl_EvalUrl(interp, bytes); } return result; } # Tcl\_EvalFile int Tcl_EvalFile(interp, fileName) Tcl_Interp *interp; /* Interpreter in which to process file. */ char *fileName; /* Name of file to process. Tilde-substitution * will be performed on this name. */ { int result, length; struct stat statBuf; Interp *iPtr; Tcl_DString nameString; char *name, *string; Tcl_Channel chan; Tcl_Obj *objPtr; name = Tcl_TranslateFileName(interp, fileName, &nameString); if (name == NULL) { return TCL_ERROR; } result = TCL_ERROR; if (TclStat(name, &statBuf) == -1) { Tcl_SetErrno(errno); Tcl_AppendResult(interp, "couldn't read file \"", fileName, "\": ", Tcl_PosixError(interp), (char *) NULL); goto end; } chan = Tcl_OpenFileChannel(interp, name, "r", 0644); if (chan == (Tcl_Channel) NULL) { Tcl_ResetResult(interp); Tcl_AppendResult(interp, "couldn't read file \"", fileName, "\": ", Tcl_PosixError(interp), (char *) NULL); goto end; } result = Tcl_EvalChannel(interp, chan); end: Tcl_DStringFree(&nameString); return result; } # Tcl\_EvalUrl int Tcl_EvalUrl(interp, fileName) Tcl_Interp *interp; /* Interpreter in which to process file. */ char *fileName; /* Name of URL to process. */ { return TCL_ERROR; } # Tcl\_EvalChannel int Tcl_EvalChannel(interp, chan) Tcl_Interp *interp; /* Interpreter in which to process file. */ Tcl_Channel chan; /* Name of file to process. */ { int result, length; struct stat statBuf; char *oldScriptFile; Interp *iPtr; char *name, *string; Tcl_Obj *objPtr; result = TCL_ERROR; objPtr = Tcl_NewObj(); if (Tcl_ReadChars(chan, objPtr, -1, 0) < 0) { Tcl_Close(interp, chan); Tcl_AppendResult(interp, "couldn't read file \"", fileName, "\": ", Tcl_PosixError(interp), (char *) NULL); goto end; } if (Tcl_Close(interp, chan) != TCL_OK) { goto end; } iPtr = (Interp *) interp; oldScriptFile = iPtr->scriptFile; iPtr->scriptFile = fileName; string = Tcl_GetStringFromObj(objPtr, &length); result = Tcl_EvalEx(interp, string, length, 0); iPtr->scriptFile = oldScriptFile; if (result == TCL_RETURN) { result = TclUpdateReturnInfo(iPtr); } else if (result == TCL_ERROR) { char msg[200 + TCL_INTEGER_SPACE]; /* * Record information telling where the error occurred. */ sprintf(msg, "\n (file \"%.150s\" line %d)", fileName, interp->errorLine); Tcl_AddErrorInfo(interp, msg); } end: Tcl_DecrRefCount(objPtr); return result; } # Comments The VFS extension interface of Tcl 8.4 plus the tclvfs and vfs::http packages provide the ability to [source] an URL. I believe that makes this proposal out of date. # Copyright This document has been placed in the public domain. |
Name change from tip/84.tip to tip/84.md.
|
| < | < | | | | | | | | > | | | | | | | | | > | 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 | # TIP 84: Add control for mouse movement filtering Author: Jyrki Alakuijala <[email protected]> Author: Jeff Hobbs <[email protected]> State: Final Type: Project Vote: Done Created: 26-Feb-2002 Post-History: Tcl-Version: 8.4 ----- # Abstract When the mouse is moved, the Tcl/Tk system eats most of the mouse movement events and only the last movement event when Tcl/Tk is not busy is stored in the event queue. I would like to obtain all the movement events from the X-server or the Windows UI. # Rationale I have an artistic drawing program where I need to track mouse as accurately as possible. At the moment I poll the _XQueryPointer\(\)_ in the busy loops to create \(pseudo\)events in the C-side of the code to compensate for the missing events, but \(of course\) this does not work in Windows. I would like to have an option for the widget system or for the window control so that a window \(or, alternatively all the windows\) could receive all the movement events instead of only the last buffered one. This has been a problem for me since 1995 and has - at many times - caused me to consider changing the widget system. # Implementation int Tk_CollapseMotionEvents(Display *display, int collapse) A reference implementation is SF Tk patch 564642, which adds a flag to the TkDisplay that specifies whether motions events should be collapsed or not. The default is the current behavior of collapsing these events. # Copyright This document has been placed in the public domain. |
Name change from tip/85.tip to tip/85.md.
|
| < | < | | | | | | | | | > | | | | | | | | | | | | | | | | | | | | < < | > > | | | | | | | | | | | | | | < > | | < > | | | | < > | | | | | | | | | | | | | | < < > > | < > | | | < > | | | < > | | | | | | | | | | | | | | | | | | | | | < > | | | | | | | | | | | | | | > | 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 | # TIP 85: Custom Comparisons in Tcltest Author: Arjen Markus <[email protected]> Author: Don Porter <[email protected]> State: Final Type: Project Vote: Done Created: 31-Jan-2002 Post-History: Keywords: test,string comparison,floating-point Tcl-Version: 8.4 ----- # Abstract This TIP proposes a simple mechanism to make the _tcltest_ package an even more flexible package than it already is by allowing the programmer to define his or her own comparison procedures. Such procedures can deal with issues like allowing a \(small\) tolerance in floating-point results. # Rationale The _test_ command of the package _tcltest 2.0_ supports the comparison of the actual result with the expected result by a number of methods: exact matching, glob-style matching and matching via a regular expression, according to the _-match_ option. The flexibility is indeed enhanced over the package _tcltest 1.0,_ as it is now much easier to allow for small variations in _string_ results. But it is nearly impossible to define an accurate test that checks if floating-point results are the "same" - exact matching will seldom suffice due to platform-specific round-off errors or differences in formatting a floating-point number \(_0.12_ versus _.12_ for instance\). It is also impossible to compare results that are not easily expressed as strings, for instance an application that produces binary files that need to be compared or simply very long strings - these could easily be stored in an external file, but would be awkward in a file with a large number of such tests. # Proposal The package _tcltest 2.0.2_ defines an internal comparison procedure, _CompareStrings_ that performs matching according to the three built-in _-match_ options of _test_. This procedure can easily be replaced by one that invokes registered commands or procedures. Such a command or procedure takes two arguments and returns 1 for a match and a 0 for failure, just as _CompareStrings_ does in the current implementation: proc myMatchProc { expected actual } { if { $expected (is somehow equal) $actual } { return 1 } else return 0 } } A new public command _customMatch_ is proposed for the purpose of registering these matching commands. It can register a procedure, such as _myMatchProc_ defined above: ::tcltest::customMatch mytype myMatchProc or, as in the sample implementation, an incomplete command: ::tcltest::customMatch exact [list ::string equal] When the _test_ command is called with the _-match mytype_ option, the command _myMatchProc_ will be completed with two arguments, the expected and actual results, and will be evaluated in the global namespace to determine whether the test result matches the expected result. Likewise, the _test_ option _-match exact_ will cause matching to be tested by the command _::string equal_. The default value of the _-match_ option will continue to be _exact_. Allowing procedures to be invoked by their type names gives us the flexibility to register as many such procedures or commands as required. Because this proposal adds a new public command to the _tcltest_ package, the version will be incremented to 2.1. A patch to the current HEAD that implements this proposal is available as Tcl Patch 521362 at the Tcl project at SourceForge. <http://sf.net/tracker/?func=detail&aid=521362&group\_id=10894&atid=310894> # Two Examples To show how this works, we include two simple examples: * Testing a package for calculating mathematical functions like Bessel functions. * Testing for negative results, as when providing an alternative, but incompatible implementation of a feature. First, suppose you have defined a package for calculating the value of a general Bessel function, just the sort of function that returns floating-point numbers. Then the results may be imprecise due to rounding-off errors, different values of _tcl\_precision_ or, even more banally, differences in the formatting of floating-point numbers \(_0.12_ versus _.12_ for instance\). The following shows how to do this: # # Test implementation of Bessel functions # (Table only provides 4 decimals) # customMatch 4decimals matchFloat4Decimals proc matchFloat4Decimals { expected actual } { return [expr {abs($expected-$actual) <= 0.5e-4}] } test "J0-1.1" "J0 for x=1.0" -match 4decimals -body { J0 1.0 } -result 0.7652 test "J1-1.1" "J0 for x=1.0" -match 4decimals -body { J1 1.0 } -result 0.4401 The second example occurs for instance when testing alternative implementations: you want to check that the original standard feature is failing whereas the new but incompatible alternative gets it right. Then: proc matchNegative { expected actual } { set match 0 foreach a $actual e $expected { if { $a != $e } { set match 1 break } } return $match } customMatch negative matchNegative # # Floating-point comparisons are imprecise. The following # test returns typically such a list as {643 1357 1921 79 781 1219} # so nothing even close to the expected values. # test "ManyCompares-1.2" "Compare fails - naive comparison" \ -match negative -body { set naiv_eq 0 set naiv_ne 0 set naiv_ge 0 set naiv_gt 0 set naiv_le 0 set naiv_lt 0 for { set i -1000 } { $i <= 1000 } { incr i } { if { $i == 0 } continue set x [expr {1.01/double($i)}] set y [expr {(2.1*$x)*(double($i)/2.1)}] if { $y == 1.01 } { incr naiv_eq } if { $y != 1.01 } { incr naiv_ne } if { $y >= 1.01 } { incr naiv_ge } if { $y > 1.01 } { incr naiv_gt } if { $y <= 1.01 } { incr naiv_le } if { $y < 1.01 } { incr naiv_lt } } set result [list $naiv_eq $naiv_ne $naiv_ge $naiv_gt $naiv_le $naiv_lt] } -result {2000 0 2000 0 2000 0} makes sure that a mismatch is treated as the expected outcome. # Alternatives and objections Of course, it is possible to achieve these effects within the current framework of _tcltest_, by putting these match procedures inside the body of the test case. No extra user command would be necessary then. There are at least two drawbacks to this approach: * The result against which we want to match is hidden in the code * If the test fails, the actual result is not printed \(at least not by the _tcltest_ framework\). As a matter of fact, the proposed mechanism actually simplifies the current implementation of the three match types to a certain degree by turning a switch between the three types into an array index. # See Also Tcl Feature Request 490298. <http://sf.net/tracker/?func=detail&aid=490298&group\_id=10894&atid=360894> # History _Cameron Laird_ was quite enthousiastic about the idea of providing custom match procedures. _Mo DeJong_ requested the explicit examples \(the second is actually the situation that triggered this TIP in the first place\). _Don Porter <[email protected]>_ revised the registration mechanism such that an arbitrary set of matching commands or procedures can be supported. His suggestions led to a revision of the TIP. He also revised the draft implementation. # Copyright This document is placed in the public domain. |
Name change from tip/86.tip to tip/86.md.
|
| < | < | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 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 | # TIP 86: Improved Debugger Support Author: Peter MacDonald <[email protected]> Author: Peter MacDonald <[email protected]> State: Draft Type: Project Vote: Pending Created: 08-Feb-2002 Post-History: Tcl-Version: 8.7 ----- # Abstract This TIP proposes the storage by Tcl of source code file-name and line-numbering information, making it available at script execution time. It also adds additional **trace** and **info** subcommands to make it easier for a debugger to control a Tcl script much as _gdb_ can control a C program. # Rationale Currently, although Tcl provides quite reasonable information to users in error traces, the line numbers within those traces are always relative to the evaluation context containing them \(often the procedure, but not always\) and not to the script file containing the procedure. This is substantially different to virtually every other computer language and makes correlating errors with the source line that caused them much more difficult. This also makes coupling a Tcl interpreter to an external debugging tool more difficult. This TIP proposes adding new interfaces to the Tcl core to make such debugging activity easier. A new **trace execution** option enables Tcl to track line number and source file information associated with statements being executed and call a single callback. A new **info line_ option provides access to line number information. As a result, it becomes a simple matter to implement a debugger for Tcl, in Tcl. Furthermore, the implementation also serves as example usage of the C interface, enabling similar capabilities at the lower level. A simple Tcl debugger, _tgdb_, written in Tcl and emulating _gdb_, is included with this TIP to demonstrate the use of this interface. _tgdb_ runs and controls a Tcl application in a sub-interp using **trace execution** and **interp alias**. It supports breakpoints on lines/procs/vars/etc, single-stepping, up/down stack and evals. It is designed to work both as a commandline and a slave process \(see _Reference Implementation_\). Finally, upon error within a procedure, the file path and absolute \(as opposed to relative\) line number are printed out when available, even in the case where called from an after or callback invocation. Aside from aiding the user in more easily locating and dealing with errors, the message is machine parseable For example: automatically bring the user into an editor at the offending line. # Specification A new **execution** subcommand to the **trace** command. > **trace execution** _target_ ?_level_? This arranges for an execution trace to be setup for commands at nesting _level_ or above, thereby providing a simple Tcl interface for tracing commands to say, implement a debugger. With no arguments, the current target is returned. If target is the empty string, the execution trace is removed. The _target_ argument is assumed to be a command string to be executed. When level is not specified, it defaults to 0, meaning trace all commands. For each traced command, the following data will be produced: * linenumber > The line number the instruction begins on. * filename > The fully normalized file name. * nestlevel > The nesting level of the command. * stacklevel > The stack call level as per **info level**. * curnsproc > The current fully qualified namespace/function. * cmdname > The fully qualified command name of the command to be invoked. * command > The command line to be executed including arguments. * flags > Integer bit flags, currently bit 1 is set for breakpoint. The target is presumed to be a valid Tcl command onto which is appended the above arguments before evaluation. Any return from the command other than a normal return results in the command not being executed. As with all traces, execution tracing is disabled within a trace handler. Second, a new **line** subcommand to **info** gives access to the file path and line number information. It takes subcommands of its own in turn: * **info line current** > Returns a list with two items: the line number and file name of the current statement. * **info line number** _proc_ ?_line_? > Get/set the line number for the start of _proc_. In get mode, returns the definition line number in the message body. * **info line level** _number_ > Like the info level command, but returns the line number and file name from which the call at level number originates. For use with _trace execution_. * **info line file** ?_proc_ ?_file_?? > Get/set the sourced file path for _proc_. If _proc_ is not specified, dump all known sourced file paths. * **info line find** _file line_ > Given a file path and line number, return the _proc_ name containing line number _line_. A new nonstatic procedure _TclFindProcByLine\(\)_ provides this function. * **info line relativeerror** ?_bool_? > Set to 1 to disable absolute line number and file path on a procedure error. This demotes procedure traceback errors to the same format as all other traceback errors, that is, using the relative the line number and file name. These exhibit the following behavior: * _What does this do when you redefine a proc?_ > You get the values from the latest definition. * _What about when you use interp aliases?_ > You get an error, as it is not considered a proc. * _And if proc itself gets redefined by someone's special debugger?_ > If the definition is not the result of a source, the file/line come back as an empty string. Third, a new _info_ subcommand _return_. * **info return** > When in _trace execution_ mode, returns the saved last result of the previously executed command. Otherwise returns an empty string. Commands executed as part of a trace handler do not affect or change the saved last result. Forth, an additional flag option _debug_ to _trace add variable_ * **trace add variable \{read write unset debug\} command** > Used in conjuction with _read_, _write_, and _unset_, this option allows a debugger to set read/write traces that will not trigger the execution trace. In other words, it specifies that the command is debugger code that is not to be traced. Normally, debugger code is entered via the **trace execution** handler and so has tracing disabled. This just provides a similar feature for **trace variable** Fifth, a new **breakpoint** subcommand to the **trace** command. > **trace breakpoint** ??_line file_ ?_level_ ...?? The _trace breakpoint_ manages a list of breakpoints that cause an _execution trace_ to trigger, even when the nestlevel is exceeded. With no arguments it returns a ternery list of all breakpoints in sets of the triples: line, file, and state. With two arguments, the current state for the breakpoint is returned. With three or more arguments, new breakpoints are created. If created with a state of zero, the breakpoint is considered inactive. Setting the state of a breakpoint to the empty string effectively deletes the breakpoint. A state set to an N greater than zero triggers every Nth time. # Changes Sourced file paths are stored per interp in a hash table. File/line numbering information is also stored in the _Interp_, _Proc_, _After_, and _CallFrame_ structures. Newline counting/shifting code was added to _proc_, _while_, _for_, _foreach_, and _if_. All but the non-trivial code is active only when the new TRACE\_LINE\_NUMBERS interp flag is active, which is the case when using _trace execution_. Most new variables within Interp are in the struct subfield sourceInfo of type _Tcl\_SourceInfo_, which can be retrieved via the new _Tcl\_GetSourceInfo\(interp\)_ stubbed/public call. # Overhead/Impact The runtime impact to Tcl should be modest: a few 10's of kilobytes of memory, even for moderately large programs. Most of the space impact occurs in storing the file paths. A typical example from a large system: 100 sourced files * 100 bytes = 10K. The other space overhead adds up to several words \(8 bytes on a 32-bit platform\) per defined procedure, plus an additional words in the _Interp_ structure. Runtime processing overhead should be negligible. However, there have been no benchmarks done to validate these assertions. # Reference Implementation This patch is against Tcl 8.4.9 and represents a complete rework of the approach. <http://pdqi.com/download/tclline-8.4.9.diff.gz> There is a simple demonstration debugger script: _tgdb.tcl_. <http://pdqi.com/download/tgdb.tcl> # Previous/Old Reference Implementation <http://pdqi.com/download/tclline-cvs.diff.gz> - Patch against CVS head. <http://pdqi.com/download/tclline-8.4.6.diff.gz> - Patch against Tcl 8.4.6 The CVS patch was against the CVS head is as of June 13/2004. These have been lightly tested against numerous small Tcl programs. There is also an initial version of a debugger: _tgdb_. <http://pdqi.com/download/tgdb-2.0.tar.gz> _tgdb_ emulates the basic commands of _gdb_ \(_s_, _n_, _c_, _f_, _bt_, _break_, _info locals_, etc\). This newest version also supports watchpoints and display variables. With _load_ and _run_ commands added, _tgdb_ should probably work even with _emacs_ and _ddd_. An additional package _pdqi_ provides _tdb_, a GUI front-end to _gdb_, modified to also work with _tgdb_. # Possible Future Enhancements Build and store a line number table internally during parse? Line number lookup via the source string. A simple way to implement this might be to lookup string against the _codePtr->source\+bestSrcOffset_ as returned by _GetSrcInfoForPc\(\)_. Add special handling for eval. Cases like _eval $str_ should eventually be changed to report a line number of 0 \(or more likely the line number of the original statement\) for all statements with any argument involving a sub-eval. Possibly implement character offsets within a line. # Notes A test has been added to the tests/trace.test. A utility _trcline.tcl_ is provided that the test uses to provide some measure of the accuracy of the line number tracing. # Comments and Feedback Jeff Hobbs asked what about **interp alias**, etc. * Updated TIP to document cases Jeff Hobbs notes filename storage is inefficient and finalization * Code changed to just increment ref count * **TODO:** What needs to be done for _Tcl\_Finalize_? Neil Madden/Stephen Trier comment on info subcommand names _line_, _file_ and _proc_ and possible future uses for _line_ * Changed to a single subcommand _line_ and use sub-sub commands. * Additional subsubcommands can easily be added. Donal Fellows writes: Is there a way to do an equivalent of _\#line_ directives in C * we can now set line number etc of a proc. Is that enough? Donald Porter notes that changing Tcl\_Parse breaks binary compatibility * Move all parse variables to Interp and save/restore values on entry/exit to Tcl\_EvalEx and TclCompileScript. Donald Porter notes that the hash table should be per Interp * Code changed to move hash table to Interp. Mo DeJong notes: file path should be used in place of file name * TIP updated to use path where appropriate Mo DeJong suggests to maybe use _TclpObjNormalizePath\(fileName\)_ * No action yet Donal Fellows objects to no support for **proc**s in subevals and Andreas Kupries suggests defining a line number _Tcl\_Token_ type. * Add support for **proc** in subeval by addition to _ResolvedCmdName_ * This is now fixed. Donal Fellows asks if trace is disabled in the execution handler, how tracing to a sub-interp would work, and clarification on the purpose and use of trace variable \{debug\}. * The documentation was updated to clarify these points. # Copyright This document has been placed in the public domain. _tgdb_ and _pdqi_ have a BSD copyright by Peter MacDonald and PDQ Interfaces Inc. |
Name change from tip/87.tip to tip/87.md.
|
| < | < | | | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 87: Allow Tcl Access to the Recursion Limit Author: Stephen Trier <[email protected]> Author: Richard Suchenwirth <[email protected]> State: Final Type: Project Vote: Done Created: 19-Feb-2002 Post-History: Discussions-To: news:comp.lang.tcl Keywords: Tcl_SetRecusionLimit,recursion limit Tcl-Version: 8.4 ----- # Abstract An extension to the [interp] command, [interp recursionlimit], will permit Tcl scripts to control their own recursion limits. Until now, this limit has been changeable from a C API, but not from within Tcl. # Rationale As of Tcl 8.4a3, Tcl scripts must live with the default recursion depth of 1000 nested calls to the _Tcl\_Eval_ family of functions or resort to C code to change the limit. Nevertheless, Tcl programmers may find it useful to reduce the limit when debugging or to increase it for scripts that include deeply recursive functions. The changes proposed in this TIP will make this possible in pure Tcl code. # Specification generic/tclInterp.c: Add subcommands to [interp] and to the slave interpreter object command with the following syntax: > interp recursionlimit _path_ _?newlimit?_ > _slave_ recursionlimit _?newlimit?_ > The parameter _newlimit_ must be a positive integer. When it is present, the limit is changed to _newlimit_ and the command returns the new recursion limit. If the _newlimit_ parameter is absent, the command returns the current recursion limit. > No maximum value is enforced. It is the programmer's responsibility to ensure the recursion limit will not overflow the process stack. > A safe interpreter is not allowed to change the recursion limit for itself nor for any other interpreter. Attempting to do so will generate an error. Safe interpreters are allowed to query recursion limits. > If an interpreter changes its own recursion limit to a value lower than the current Tcl\_Eval nesting level, the limit will be changed, then an error message appropriate to this particular situation will be issued by the recursionlimit command. \(Error text: "falling back due to new recursion limit"\) > If an interpreter changes a sub-interpreter's recursion limit to less than the sub-interpreter's current Tcl\_Eval nesting level, no immediate error is issued. The sub-interpreter will throw a "too many nested calls to Tcl\_Eval \(infinite loop?\)" error if its nesting is still deeper than its recursion limit when next a command is executed in its context. generic/tclTest.c: Remove the now-unnecessary testsetrecursionlimit command. doc/interp.n: Add documentation for the new subcommands, including a warning about stack overflow, much like the warning in the documentation for _Tcl\_SetRecursionLimit\(\)_. test/interp.test: Add tests for the new subcommands. # Comments Received Discussion of this TIP took place in the following threads: <http://groups.google.com/groups?hl=en&threadm=3C6D0A88.5DC9D8B4%40utdt.edu> <http://groups.google.com/groups?hl=en&threadm=3C73E98A.8ED9DDE6%40cisco.com> <http://www.geocrawler.com/mail/thread.php3?subject=%5BTCLCORE%5D\+TIP\+%2387%3A\+Allow\+Tcl\+Access\+to\+the\+Recursion\+Limit&list=7375> Using a command or variable _::tcl::recursionLimit_ to manipulate the limit was initially considered, but Miguel Sofer suggested making the function a subcommand of [interp] because the recursion limit is logically an attribute of each interpreter. Miguel also pointed out that implementing _TclpCheckStackSpace\(\)_ for Unix would mitigate the dangers of setting the recursion limit too high. comp.lang.tcl saw some discussion of whether it would be appropriate to have a way to completely remove the recursion limit. The consensus was to not add such a feature. The initial version of this TIP did not provide for a diagnostic error message for the case where the nesting is already deeper than the new recursion level. Ken Fitch, Don Porter, Miguel Sofer, and Donal Fellows discussed whether this was important. This version of the TIP uses Donal Fellows's suggestion of changing the recursion limit as requested, but providing a meaningful error message if the nesting is too deep for the new limit. Donal Fellows suggested that slave interpreters should inherit their recursion limit from their parent. As it turns out, this behavior was already present but was not documented. The reference implementation documents it. # Reference Implementation An implementation of this TIP, with tests and documentation, is patch number 522849 on SourceForge. # Copyright This document is in the public domain. |
Name change from tip/88.tip to tip/88.md.
|
| < | < | | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 88: Extend Tcl Process Id Control via 'pid' Author: Jeff Hobbs <[email protected]> Author: Vince Darley <[email protected]> State: Rejected Type: Project Vote: Done Created: 11-Mar-2002 Post-History: Tcl-Version: 8.4 Obsoleted-By: 240 ----- # Abstract This TIP proposes extended the [pid] command to provide more control over native processes in Tcl. # Rationale Certain process control functions have shown themselves to be portable and of high usefulness to Tcl programmers. Most of these already exist in TclX, but simply requiring that extension isn't always acceptable. The [pid] command in Tcl is a command that is often overlooked, and so simple that it lends itself easily to being enhanced with new syntax. This TIP proposes adding subcommands to [pid] that extend the process control functionality of pure Tcl. # Specification pid ?fileId? pid terminate ?-force? ?--? pid ?pid ...? The first line is the current definition for [pid], which is to return the name of the current process id, or that attached to a _fileId_ \(as returned by [open] or [socket]\). I propose to add only _terminate_ initially. This command is adapted almost directly from TclX's signal handling, but changed to work as a subcommand of [pid]. This is to satisfy one of the most common requests from users regarding process management - killing a known process. It also establishes the framework of extending [pid] for future modifications. The ?-force? argument causes a forceful termination \(the usage of SIGKILL on Unix, for Windows and Mac termination is already forceful\). # Reference Implementation Although TclX's current documentation denies it, the _send_ is already implemented for Windows \(as _kill_ under TclX\) as well as Unix. Macintosh implementations for OS 9 and below would need to be created, or the documentation would need to stress that these are not available there \(OS X is Unix based\). Jim Ingham notes that a variant of _kill_ could be created for OS 9. These functions are really meant to round out the process control functionality in Tcl \(started with _exec_ and _open\|_\), which are already of limited portability to Mac OS 9 \(but undeniable usefulness elsewhere\). File: _tcl/mac/tclMacChan.c_ File: _tcl/unix/tclUnixPipe.c_ File: _tcl/win/tclWinPipe.c_ Function: _Tcl\_PidObjCmd_ # Future Potential What this also provides is a blueprint for future process management functions like these: pid id ?-user ?userIdOrName?? ?-group ?groupIdOrName?? ?-parent parentId? pid wait ?-nohang bool? ?-untraced bool? ?-group bool? ?fileIdOrPid? pid nice ?-level niceLevel? fileIdOrPid pid list ?pattern? pid id ?-session id? ?-processgroup id? pid handle action signal ... pid send signalType fileIdOrPid ?fileIdOrPid ...? [pid wait] was in the initial tip, but it was recommended to rework it with callback to make it much more useful to the user. The [pid id] command was intended for Unix only, operating on the current process id, and would function similar to the [file attributes] command, but Windows NT does have similar functionality. The _-user_ and _-group_ options will return the name if possible, otherwise the id. The _-parent_ option would be read-only \(like _-longname_ for [file attributes]\). [pid send] suffers from cross-platform portability as well. On Windows, you can only _raise_ signals inside of your own process. [pid nice] is easy to implement, while [pid list] is very much platform sensitive. [pid handle] is for signal handling, another oft-requested feature for the core, and would be based on the TclX [signal] command \(perhaps named _trap_ as in Expect?\). It could be massaged to various forms. These aren't to be addressed in this TIP, but are just ideas for the future. # Comments pid kill ?-group bool? ?-signal signalType? fileIdOrPid ?fileIdOrPid ...? This was the original form for [pid send], but it was noted that we are really sending signals. While I prefer the specificity of users recognizing _kill_ as a command, what this really does is send specific signals \(ANSI C specifies SIGABRT, SIGINT and SIGTERM, and for Unix we would handle the other POSIX names too\). Thus I changed it to the _send_ command documented above. [process] rather than [pid] seems a more logical name for this command, but we are working within the constraints of the existing commands in order to prevent command bloat. There is still logic in the naming, as we are dealing with process ids. [pid terminate] was also recommended to have the ability to terminate a process _and_ all its children. This would be useful, but is not in the scope of the current tip. # Copyright This document has been placed in the public domain. |
Name change from tip/89.tip to tip/89.md.
|
| < | < | | | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | < > | | | | | < | > | | | | | | < | > | | | | | | | | | < | > | | | | | | | | | < | > | | | | | | | < > | | < > | | | < | > | | | | | | | | | | | | | | | | | | < > | | | | | | | | | | | | | | < > | < > | | < > | | | | | | | | < > | | | | | | | < > | | | | | | | | | | | | | | | | < > | | | | | | | | | | | | | | | | | | | | | < > | | | | | | | | | | | | | | | | | < > | | | | | | | | | | | < > | | | | | | < > | | | < > | | | | | | | < > | | | | | | | | | | | | | | | | | < > | | | | | | | | | | | | | | | | | | | | | | | | | < > | | < > | | | | | < > | | < > | | | | | | | | < > < > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | < > | | | | | | < > | | | | | | | | | | | | | | | | | | | | | | | | | | | | < > | | | | | | | | | | | | | < < > > | | | | < > | | | < > | | | | < < > > | | | | | | | | | | | | | | | | | < > | | | | < > | | | | < > | | | | | | < > | | | | | | | | | | | | | < > | | | | | | | | | | | | | | | | | | | | | < > | | | | | | | | | | < > | | | | | | | | | | | | < < > > | | | | | | < < > > | | | | | | < > | | | < > | < > | | | | | | | < > | | | | | < > | | | < > | | | | | | | | | | | | | | | | | | | | | | | | | | | | < | > | > | 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 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 | # TIP 89: Try/Catch Exception Handling in the Core Author: Tom Wilkason <[email protected]> Author: Frank Pilhofer <[email protected]> State: Withdrawn Type: Project Vote: Pending Created: 11-Mar-2002 Post-History: Discussions-To: news:comp.lang.tcl Tcl-Version: 8.6 Obsoleted-By: 329 ----- # Abstract This TIP proposes the addition of a **try**...**catch**...**finally** command to provide a more robust and powerful exception handling mechanism. # Rationale Exceptions are currently supported very well in Tcl, in fact they are a major advantage over many other languages. However the mechanism to **catch** and handle the errors is someone limited and does not promote the full use of existing error codes. Wrapper procedures can be written to improve on this, however both a performance and compatibility penalty is incurred. This TIP proposes adding a **try/catch** command to the Tcl core \(or C based Tcl library\). This implementation is not unlike those found in C\+\+, C\#, Java and Python \(to name a few languages\). An argument to add this to the core is that it modernizes the Tcl exception handling without impacting performance in any other way. **try/catch** are isolated commands that can easily be added, and do not interact with other commands or require other changes. **try/catch** is not an isolated extension that is useful for special purposes only. These commands, if implemented into the core, will be useful for any script currently using the catch construct. # Specification I propose the following two commands be added to Tcl: * **throw** command. > **throw** ?_type_? ?_message_? ?_info_? > A **throw** command with _type_ throws an error exception with the errorCode _type_. The **throw** command works as the **error** command, but the arguments are reordered to encourage the use of error-codes. The optional _message_ and _info_ parameters work as they do in the **error** command. > The throw _type_ can be any user defined or built in type, built-in types include POSIX, ARITH, CORE, REGEXP, WINDOWS, NONE, ... The _message_ is optional, and is the same as that issued by the **catch** command, **error -code error** "_message_" > An instance of **throw** with no arguments can be used within a **catch** block to immediately re-throw the current exception that is being handled by the **catch** block. When an error is re-thrown in the catch block, the current error is propagated up one level following the evaluation of the **finally** block \(if on exists\). Enclosing error handlers can then deal with the error. > Note that throw type message info > is the same as error message info type * **try** command. > **try** _body_ ?**catch** \{\{_type\_list_\} ?_ecvar_? ?_msgvar_? ?_infovar_?\} _body ..._? ?**finally** _body_? > If one or more **catch** blocks are specified, each corresponding _body_ represents a required block of code that is evaluated if the resulting errorCode matches the _type_ condition. The required body of the **finally** block is evaluated following the **try** block and **catch** block \(if any matches\). > _type\_list_ represents a list of glob style patterns used to match eache of the error-code list conditions. A match is declared if the _type\_list_ patterns or errorCode elements are exhausted \(whichever comes first\) and a mismatch has not occurred. If a match occurs, and _ecvar_ is specified, the errorCode list will be stored in _ecvar_ within the local scope prior to executing the _body_. Moreover, if a _msgvar_ or _infovar_ are specified, the error message and errorInfo contents will be stored in the local context. > If an error occurs during the **try**, and no _catch_ blocks are specified, the offending error is rethrown following execution of the _finally_ block \(if specified\). > If an error occurs during execution of a **catch** or **finally** block, this error will take precedence and will propagate upwards with a new stack trace. If an error is rethrown within a catch block, the existing stack trace will be preserved with the rethrown error. This allows later discrimination of the two different error conditions \(rethrown vs. unintended\). > Note, **catch** \{_\*_\}, if specified, will catch all remaining errors. If used, it should be placed last since each of the catch blocks are evaluated in the order specified. _type_ is that set in errorCode, and can be any user defined type, or built-in types including POSIX \*, ARITH \*, CHILD \*, CORE, REGEXP, WINDOWS, or NONE. > If one or more **catch** blocks are specified, and no **catch** block matches the errorCode condition, the error will be propagated up to the next level following evaluation of the **finally** clause \(if specified\). An enclosing **try** block \(or **catch** command\) can then be used to handle the error. > The **finally** block is used to perform all the clean up code. The **finally** body is evaluated whether the error occurs or not, or whether a **catch** block matched the errorCode. It is also evaluated if a _throw_ statement occurs within the **catch** clause. # Examples **throw** throw DEVICE "Could not write to device" **try** only \(no practical use\) try { incr i } **try - catch** try { incr i } catch * { set i 0 } **try - finally** try { . config -cursor watch #do some busy stuff here, don't care about errors } finally { . config -cursor arrow } **try - catch - catch** try { ;# Some code that will cause an error } catch {{POSIX *} eCode eMessage} { ;# Statements to handle POSIX type errors } catch {NULL eCode eMessage} { ;# Statements to handle NULL (a user created) type errors } catch {* eMessage} { ;# Statements to handle all other errors } **try - catch - catch - finally** try { ;# Some code that will cause an error } catch {POSIX eCode eMessage} { ;# Statements to handle POSIX type errors } catch {* eCode eMessage} { ;# Statements to handle all other errors } finally { ;# Statements to execute whether an error occurred or not } Re-throw **try - catch - finally** try { try { set b [expr {$a/0}] } catch {ARITH} { if {$a == 0} { throw ;# re-throw to outer try } } finally { set b 1 ;# will execute before throw above } } catch {ARITH eCode eMessage} { ;# This will catch the inner throw puts "$res" } # Revisions: Tom Wilkason March 26, 2002 * Added additional _ecvar_ and _infovar_ optional arguments to the **catch** clause. * All uncaught errors are propagated up after execution of the finally block \(if specified\). * Unanticipated errors within a **catch** or **finally** block start a new stack trace and are propagated up. * Additional _info_ optional argument added to **throw** for completeness. # Reference Implementation /* * Implementation of try/catch and throw commands according to TIP 89 */ #include <tcl.h> /* * We keep a stack of contexts; whenever we have to handle an error, * i.e. are executing a catch {} clause, we store the current error * (errorCode, errorInfo and message), so that a throw with no arguments * can re-throw it. * * This is interpreter-specific data. Each element is a list, with the * last element being the most current one. */ typedef struct { Tcl_Obj * errorCodeStack; Tcl_Obj * errorInfoStack; Tcl_Obj * errorMsgStack; Tcl_Obj * errorCodeName; Tcl_Obj * errorInfoName; } TryCatchTsd; /* * Throw an Exception * * throw ?<type> ?<message>? ?<info>?? * * Throws an exception with the errorCode <type>, the message <message> * and the errorInfo <info>. * * An instance of throw with no arguments can be used within a catch or * finally block to immediately re-throw the current exception that is * being handled by the catch block. */ static int Tcl_ThrowObjCmd (ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { TryCatchTsd * myTsd = (TryCatchTsd *) clientData; if (objc < 1 || objc > 4) { Tcl_AppendResult (interp, "wrong # args: should be \"", Tcl_GetStringFromObj (objv[0], NULL), " ?<type> ?<message>? ?<info>??\"", NULL); return TCL_ERROR; } /* * Re-throw an error */ if (objc < 2) { Tcl_Obj *errorCode, *errorInfo, *errorMsg; int lastelement; Tcl_ListObjLength (interp, myTsd->errorMsgStack, &lastelement); if (lastelement < 1) { Tcl_AppendResult (interp, "error: throw with no parameters ", "outside of a catch", NULL); return TCL_ERROR; } lastelement--; Tcl_ListObjIndex (interp, myTsd->errorMsgStack, lastelement, &errorMsg); Tcl_ListObjIndex (interp, myTsd->errorCodeStack, lastelement, &errorCode); Tcl_ListObjIndex (interp, myTsd->errorInfoStack, lastelement, &errorInfo); Tcl_ResetResult (interp); Tcl_SetObjResult (interp, errorMsg); Tcl_SetObjErrorCode (interp, errorCode); #ifdef _TCLINT Tcl_ObjSetVar2 (interp, myTsd->errorInfoName, NULL, errorInfo, TCL_GLOBAL_ONLY); interp->flags = ERR_IN_PROGRESS; #else Tcl_AddErrorInfo (interp, Tcl_GetStringFromObj (errorInfo, NULL)); #endif return TCL_ERROR; } /* * throw with parameters */ Tcl_ResetResult (interp); if (objc >= 3) { Tcl_SetObjResult (interp, objv[2]); } else { /* * fabricate some error message for human consumption */ Tcl_AppendResult (interp, "error: ", Tcl_GetStringFromObj (objv[1], NULL), NULL); } Tcl_SetObjErrorCode (interp, objv[1]); if (objc >= 4) { #ifdef _TCLINT Tcl_ObjSetVar2 (interp, myTsd->errorInfoName, NULL, objv[3], TCL_GLOBAL_ONLY); interp->flags = ERR_IN_PROGRESS; #else Tcl_AddErrorInfo (interp, Tcl_GetStringFromObj (objv[3], NULL)); #endif } /* * throw error */ return TCL_ERROR; } /* * exception handling * * try body ?catch {type-list ?ecvar? ?msgvar? ?infovar?} body ...? * ?finally body? */ static int Tcl_TryObjCmd (ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { TryCatchTsd * myTsd = (TryCatchTsd *) clientData; int currentIndex, finallyIndex, catchInfoLength, hasCatch; char * blockType; int res; /* * first check for syntactic correctness before doing anything */ if (objc < 2) { Tcl_AppendResult (interp, "wrong # args: should be \"", Tcl_GetStringFromObj (objv[0], NULL), " body ", "?catch {type-list ?ecvar? ?msgvar? ?infovar?} ", "body ...? ", "?finally body?\"", NULL); return TCL_ERROR; } currentIndex = 2; finallyIndex = -1; hasCatch = 0; while (currentIndex < objc) { blockType = Tcl_GetStringFromObj (objv[currentIndex], NULL); if (strcmp (blockType, "catch") == 0) { Tcl_Obj * typeList; int typeListLength; if (currentIndex+2 >= objc || Tcl_ListObjLength (interp, objv[currentIndex+1], &catchInfoLength) != TCL_OK || (catchInfoLength < 1 && catchInfoLength > 4) || Tcl_ListObjIndex (interp, objv[currentIndex+1], 0, &typeList) != TCL_OK || Tcl_ListObjLength (interp, typeList, &typeListLength) != TCL_OK) { Tcl_AppendResult (interp, "invalid syntax in catch clause: ", "should be \"", "catch {type-list ?ecvar? ?msgvar? ?infovar?} ", "body\"", NULL); return TCL_ERROR; } hasCatch = 1; currentIndex += 3; } else if (strcmp (blockType, "finally") == 0) { if (currentIndex+2 != objc) { Tcl_AppendResult (interp, "trailing args after finally clause", NULL); return TCL_ERROR; } finallyIndex = currentIndex; currentIndex += 2; } else { Tcl_AppendResult (interp, "invalid syntax: should be \"", Tcl_GetStringFromObj (objv[0], NULL), " body ", "?catch {type-list ?ecvar? ?msgvar? ?infovar?} ", "body ...? ", "?finally body?\"", NULL); return TCL_ERROR; } } /* * Eval main body */ res = Tcl_EvalObjEx (interp, objv[1], 0); /* * In case of error, check the catch clauses */ if (res == TCL_ERROR) { Tcl_Obj *errorCode, *errorInfo, *errorMsg; int errorCodeLength, stackLength; errorMsg = Tcl_GetObjResult (interp); errorCode = Tcl_ObjGetVar2 (interp, myTsd->errorCodeName, NULL, TCL_GLOBAL_ONLY); errorInfo = Tcl_ObjGetVar2 (interp, myTsd->errorInfoName, NULL, TCL_GLOBAL_ONLY); /* * After an error has happened, errorCode and errorInfo should * exist. */ if (errorCode == NULL || errorInfo == NULL) { Tcl_AppendResult (interp, "assertion error in try: ", "no errorCode or no errorInfo", NULL); return TCL_ERROR; } if (Tcl_ListObjLength (interp, errorCode, &errorCodeLength) != TCL_OK) { Tcl_AppendResult (interp, "assertion error in try: " "errorCode is not a list", NULL); return TCL_ERROR; } /* * push error data on stack, so that throw can rethrow the error */ Tcl_ListObjAppendElement (interp, myTsd->errorMsgStack, errorMsg); Tcl_ListObjAppendElement (interp, myTsd->errorCodeStack, errorCode); Tcl_ListObjAppendElement (interp, myTsd->errorInfoStack, errorInfo); /* * Look for a matching clause */ currentIndex = 2; while (currentIndex < objc) { blockType = Tcl_GetStringFromObj (objv[currentIndex], NULL); if (strcmp (blockType, "catch") == 0) { int typeListLength, matchIndex; Tcl_Obj *typeList; Tcl_ListObjIndex (interp, objv[currentIndex+1], 0, &typeList); Tcl_ListObjLength (interp, typeList, &typeListLength); if (typeListLength > errorCodeLength) { currentIndex += 3; continue; } for (matchIndex=0; matchIndex<typeListLength; matchIndex++) { Tcl_Obj *errorCodeItem, *typeListItem; const char *errorCodeItemStr, *typeListItemStr; Tcl_ListObjIndex (interp, errorCode, matchIndex, &errorCodeItem); Tcl_ListObjIndex (interp, typeList, matchIndex, &typeListItem); errorCodeItemStr = Tcl_GetStringFromObj (errorCodeItem, NULL); typeListItemStr = Tcl_GetStringFromObj (typeListItem, NULL); if (!Tcl_StringMatch (errorCodeItemStr, typeListItemStr)) { break; } } if (matchIndex >= typeListLength) { /* matching catch clause found */ break; } /* continue looking */ currentIndex += 3; } else { /* not a catch clause - there are no matching catch clauses */ currentIndex = objc; break; } } /* * Did we find a matching catch clause? */ if (currentIndex < objc) { Tcl_Obj *ecvar, *msgvar, *infovar; Tcl_ListObjLength (interp, objv[currentIndex+1], &catchInfoLength); /* * set variables with error data */ if (catchInfoLength >= 2) { Tcl_ListObjIndex (interp, objv[currentIndex+1], 1, &ecvar); Tcl_ObjSetVar2 (interp, ecvar, NULL, errorCode, 0); } if (catchInfoLength >= 3) { Tcl_ListObjIndex (interp, objv[currentIndex+1], 2, &msgvar); Tcl_ObjSetVar2 (interp, msgvar, NULL, errorMsg, 0); } if (catchInfoLength >= 4) { Tcl_ListObjIndex (interp, objv[currentIndex+1], 3, &infovar); Tcl_ObjSetVar2 (interp, infovar, NULL, errorInfo, 0); } /* * call body; the error code of this body takes precedence */ res = Tcl_EvalObjEx (interp, objv[currentIndex+2], 0); } /* * pop error data from stack */ Tcl_ListObjLength (interp, myTsd->errorMsgStack, &stackLength); stackLength--; Tcl_ListObjReplace (interp, myTsd->errorMsgStack, stackLength, 1, 0, NULL); Tcl_ListObjReplace (interp, myTsd->errorCodeStack, stackLength, 1, 0, NULL); Tcl_ListObjReplace (interp, myTsd->errorInfoStack, stackLength, 1, 0, NULL); } /* * Execute finally body. Preserve errorCode and friends; they might * be corrupted by the code in the body - e.g. by a try in the code, * or in a proc called by the code. */ if (finallyIndex != -1) { Tcl_Obj *errorCode, *errorInfo, *errorMsg; int finallyres, origres=res; errorMsg = Tcl_GetObjResult (interp); Tcl_IncrRefCount (errorMsg); if (origres == TCL_ERROR) { errorCode = Tcl_ObjGetVar2 (interp, myTsd->errorCodeName, NULL, TCL_GLOBAL_ONLY); errorInfo = Tcl_ObjGetVar2 (interp, myTsd->errorInfoName, NULL, TCL_GLOBAL_ONLY); Tcl_IncrRefCount (errorCode); Tcl_IncrRefCount (errorInfo); } finallyres = Tcl_EvalObjEx (interp, objv[finallyIndex+1], 0); /* * An Error in the finally clause takes precedence, else restore * previous error data */ if (finallyres != TCL_OK) { res = finallyres; } else { Tcl_SetObjResult (interp, errorMsg); if (origres == TCL_ERROR) { Tcl_SetObjErrorCode (interp, errorCode); #ifdef _TCLINT Tcl_ObjSetVar2 (interp, myTsd->errorInfoName, NULL, errorInfo, TCL_GLOBAL_ONLY); interp->flags = ERR_IN_PROGRESS; #else Tcl_AddErrorInfo (interp, Tcl_GetStringFromObj (errorInfo, NULL)); #endif } } Tcl_DecrRefCount (errorMsg); if (origres == TCL_ERROR) { Tcl_DecrRefCount (errorCode); Tcl_DecrRefCount (errorInfo); } } /* * Pass along return code */ return res; } /* * ---------------------------------------------------------------------- * * "Main" function, install our commands in the Tcl interpreter * * ---------------------------------------------------------------------- */ #undef TCL_STORAGE_CLASS #define TCL_STORAGE_CLASS DLLEXPORT EXTERN int Trycatch_Init (Tcl_Interp *interp) { TryCatchTsd * myTsd; #ifdef USE_TCL_STUBS if (Tcl_InitStubs (interp, TCL_VERSION, 0) == NULL) { return TCL_ERROR; } #else if (Tcl_PkgRequire (interp, "Tcl", TCL_VERSION, 1) == NULL) { return TCL_ERROR; } #endif /* * Allocate Tsd */ myTsd = (TryCatchTsd *) Tcl_Alloc (sizeof (TryCatchTsd)); myTsd->errorCodeStack = Tcl_NewObj (); myTsd->errorInfoStack = Tcl_NewObj (); myTsd->errorMsgStack = Tcl_NewObj (); myTsd->errorCodeName = Tcl_NewStringObj ("errorCode", -1); myTsd->errorInfoName = Tcl_NewStringObj ("errorInfo", -1); /* * add commands */ Tcl_CreateObjCommand (interp, "throw", Tcl_ThrowObjCmd, (ClientData) myTsd, NULL); Tcl_CreateObjCommand (interp, "try", Tcl_TryObjCmd, (ClientData) myTsd, NULL); /* * Ready */ Tcl_PkgProvide (interp, "trycatch", "0.1"); return TCL_OK; } # Copyright This document has been placed in the public domain. |
Name change from tip/9.tip to tip/9.md.
|
| < | < | | | | | | | | | > | | | | | | | 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 | # TIP 9: Tk Standard Library Author: Marty Backe <[email protected]> Author: Larry W. Virden <[email protected]> Author: Jeff Hobbs <[email protected]> State: Withdrawn Type: Project Vote: Pending Created: 07-Nov-2000 Post-History: Tcl-Version: 8.4 ----- # Abstract A Tk standard library shall be bundled with the core Tcl/Tk distribution. The library will consist of general purpose widgets and composite widgets for use in constructing Tcl/Tk applications. The library of Tk components will be written in Tcl/Tk. # Rationale Although Tcl "ships" with a comprehensive set of native \(compiled\) base Tk widgets, it lacks a library of composite widgets, from which sophisticated applications can readily be built with minimal reinvention. Although the Tcl community has created a wealth of general purpose Tk widgets, generally they are not centrally located or distributed, making their use problematic. This requires that Tcl programs which make use of such widgets must either distribute them or direct the end user on their acquisition and installation. Arguably, the success and higher visibility of other "competing" scripting languages can be attributed in some part to their extensive libraries. Tcl/Tk should continue this trend. Tcl is perhaps unique in that it is considered both a graphical \(Tk\) and non-graphical \(Tcl\) programming language. Work has begun in implementing a standard library for Tcl. It could be argued that Tcl/Tk's largest base, and its largest growth area, is with regards to graphical applications. To this end, Tcl needs a comprehensive, and well maintained Tk standard library. Finally, to lower the barrier of using the Tk libraries, they should be Tcl/Tk based. This helps to assure cross platform independence without requiring the user to compile code against a source distribution. # Specification * The standard Tk library will be called "tklibX.Y", where "X.Y" will follow the version number of the Tcl/Tk distribution that it's compatible with. * Major/minor releases of the tklib shall coincide with the major/minor releases of Tcl/Tk. That is, if Tcl/Tk version 8.5 is |
︙ | ︙ | |||
81 82 83 84 85 86 87 | by the component. A picture is worth a thousand words! The Tk, BWidgets, and Iwidgets demos are prime examples to be emulated. * Tklib components can be dependent on other tklib components. If tklib and tcllib become coordinated efforts, the tklib components can be dependent on tcllib components. | | | | | | > | 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 | by the component. A picture is worth a thousand words! The Tk, BWidgets, and Iwidgets demos are prime examples to be emulated. * Tklib components can be dependent on other tklib components. If tklib and tcllib become coordinated efforts, the tklib components can be dependent on tcllib components. * The tklib can \(and hopefully will\) include megawidgets. * Tklib components shall be written in Tcl/Tk. * Tklib components shall be implemented in their own namespace and distributed in package form. * Tklib components do not have to be unique with regards to other tklib components, although there shall be differentiating characteristics between them. There is more then one way to skin a cat. * The tklib shall not contain applications, IDEs, or development tools. # Notes A tklib module has been created next to the aforementioned tcllib at <http://tcllib.sf.net/> This creates the basic infrastructure for people to work in, but does not set any status related to the core as yet. ---- _Larry W. Virden writes_: > It appears to me that tklib isn't going to be bundled with the tk source code distribution any more than tcllib getting distributed with the tcl core distribution. > If the TCT concurs that this is the case, then I would propose that this TIP be withdrawn. tklib exists now, and to date, submissions are extremely rare. > Here we are, some time later, and no action still on either withdrawing or rejecting this TIP. Perhaps some action could be taken on this TIP? ---- # Copyright This document has been placed in the public domain. |
Name change from tip/90.tip to tip/90.md.
|
| < | < | | | | | | | | > | | | | | | | | | | | | | | | | | | < > | < | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | < > | | | < | > | | | | | | | | | | < > | | | | | | | | | | < > | | < > | | | | | | | | | | | < > | | < < | > > | | | | | | | | < > | < > | < > | | | | | < > | | | | | | | < > | | < < | > > | | | | | | | | | | | | | | | | | | | | | | | | | < > | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 | # TIP 90: Enable [return -code] in Control Structure Procs Author: Don Porter <[email protected]> Author: Donal K. Fellows <[email protected]> State: Final Type: Project Vote: Done Created: 15-Mar-2002 Post-History: Tcl-Version: 8.5 ----- # Abstract This TIP analyzes existing limitations on the coding of control structure commands as _proc_s, and presents expanded forms of _catch_ and _return_ to remove those limitations. # Background It is a distinguishing feature of Tcl that everything is a command, including control structure functionality that in many other languages are part of the language itself, such as _if_, _for_, and _switch_. The command interface of Tcl, including both a return code and a result, allows extensions to create their own control structure commands. Control structure commands have the feature that one or more of their arguments is a script, often called a _body_, meant to be evaluated in the caller's context. The control structure command exists to control whether, when, in what context, or how many times that script is evaluated. When the body is evaluated, however, it is intended to behave as if it were interpreted directly in the place of the control structure command. The built-in commands of Tcl provide the ability for scripts themselves to define new commands. Notably, the _proc_ command makes this possible. In addition, other commands such as _catch_, _return_, _uplevel_, and _upvar_ offer enough control and access to the caller's context that it is possible to create new control structure commands for Tcl, entirely at the script level. Almost. There is one limitation that separates control structure commands created by _proc_ from those created in C by a direct call to _Tcl\_Create\(Obj\)Command_. It is most easily seen in the following example that compares the built-in command _while_ to the command _control::do_ created by _proc_ in the control package of tcllib. % package require control % proc a {} {while 1 {return -code error}} % proc b {} {control::do {return -code error} while 1} % catch a 1 % catch b 0 The control structure command _control::do_ fails to evaluate _return -code error_ in such a way that it acts the same as if _return -code error_ was evaluated directly within proc _b_. # Analysis There are two deficiencies in Tcl's built-in commands that lead to this incapacity in control structure commands defined by _proc_. First, _catch_ is not able to capture the information. Consider: % set code [catch { return -code error -errorinfo foo -errorcode bar baz } message] After evaluation, _code_ contains "2" \(_TCL\_RETURN_\), and _message_ contains "baz", but the other values are locked away in internal fields of the _Tcl\_Interp_ structure as _interp->returnCode_, _interp->errorCode_, and _interp->errorInfo_. The "-errorcode" and "-errorinfo" values will be copied to the global variables "::errorCode" and "::errorInfo", respectively, but there will be no way at the script level to get at the _interp->returnCode_ value which was the value of the original "-code" option. Second, even if the information were available, there is no built-in command in Tcl that can be evaluated within the body of a proc to make the proc itself act as if it were the command _return -code_. Stated another way, it is not possible to create a command with _proc_ that behaves exactly the same as _return -code_. Because of that, it is also not possible to create a command with _proc_ that behaves exactly the same as _while_, _if_, etc. - any command that evaluates any of its arguments as a script in the caller's context. This is a curious, and likely unintentional, limitation. Tcl goes to great lengths to be sure I can create my own _break_ replacement with _proc_. proc myBreak {} {return -code break} It would be a welcome completion of Tcl's set of built-in commands to be able to create a replacement for every one of them using _proc_. # Specification The _return_ command shall have syntax: return ?option value ...? ?result? There can be any number of _option value_ pairs, and any value at all is acceptable for an _option_ argument. The legal values of a _value_ argument are limited for some _option_s, as follows: > the _value_ after a "-code" must be either an integer \(32-bit only\), or one of the strings, "ok", "error", "return", "break", or "continue", just as in the 8.4 spec for _return_. The default _value_ for the "-code" option is "0". > the _value_ after a "-level" must be a non-negative integer. The default _value_ for the "-level" option is "1". > the _value_ after a "-options" must be a dictionary \([[111]](111.md)\). The default _value_ for the "-options" option is an empty dictionary. The keys and values in the dictionary _value_ of the "-options" option are pulled out and treated as additional _option value_ arguments to the _return_ command. Note that this "-options" option for option expansion is offered only because Tcl itself has no syntax for argument expansion, as observed many, many times before \(for example, [[103]](103.md)\). The _result_ argument, if any, is stored in the interp as the result of the _return_ command. In default operation, this becomes the result of the procedure in which the _return_ command is evaluated. The return code of the _return_ command is determined by the _value_s of the "-code" and "-level" options. If the _value_ of the "-level" option is non-zero, then the return code of _return_ is TCL\_RETURN. If the _value_ of the "-level" option is "0", then the return code of _return_ is the _value_ of the "-code" option, translated from string, as needed. In this way, return -level 0 -code break is a synonym for break while return -code break spelled out with defaults filled in as: return -level 1 -code break continues to function as before, causing the procedure in which the _return_ is evaluated to return the TCL\_BREAK return code. All _option value_ arguments to _return_ are stored in a return options dictionary kept in the interp, just as the _result_ argument gets stored in the result of the interp. The TclUpdateReturnInfo\(\) function is modified, so that each level of procedure returning decrements the value of the "-level" key in the return options dictionary. When the value of the "-level" key reaches "0", the return code from the current procedure will be the value of the "-code" key in the return options dictionary. Otherwise, the return code of the current procedure will be TCL\_RETURN. In this way, return -level 2 -code ok is equivalent to return -code return and should \(absent some intervening _catch_\) cause a normal return to the caller's caller. Likewise, return -level 3 -code ok would cause a normal return to the caller's caller's caller \(again absent an intervening _catch_\), something that can't currently be accomplished. The _catch_ command shall have syntax: catch script ?resultVar? ?optionsVar? The new argument _optionsVar_, if present, will be the name of a variable in which a dictionary of return options should be stored. The return options stored in that dictionary are exactly those needed so that the evaluation of catch $script result options return -options $options $result is completely indistinguishable \(except for the existence and values of variables "result" and "options"\) from the direct evaluation of _$script_ by the interpreter. In particular, any values of the "::errorCode" and "::errorInfo" variables are the same as if there were never a _catch_ in the first place. In addition, when the result of _catch_ is TCL\_ERROR, the value in the _errorLine_ field of the _Interp_ struct will be stored as the value of the "-errorline" key in the return options dictionary. This specification may seem a bit complex, but it makes possible very simple solutions to the problems posed above. # Examples First lets revisit the analysis: % set code [catch { return -code error -errorinfo foo -errorcode bar baz } message options] After evaluation, _code_ contains "2" \(_TCL\_RETURN_\), _message_ contains "baz", and now _options_ contains: -errorcode bar -errorinfo foo -code 1 -level 1 So, the _options_ variable now contains the information that was previously inaccessible. We can now return -options $options $message to get the same results as if the _catch_ had never been there in the first place. In 8.4 Tcl, it is not possible to implement a replacement for the _return_ command as a proc. After this proposal, such a replacement is: proc myReturn args { set result "" if {[llength $args] % 2} { set result [lindex $args end] set args [lrange $args 0 end-1] } set options [eval [list dict create -level 1] $args] dict incr options -level return -options $options $result } In every way _myReturn_ should be an equivalent to _return_. The new ability to exactly reproduce stack traces makes a _catch_ of large scripts more attractive. For example, a procedure that allocates some resource, then performs operations, and finally frees the resource before returning. In order to be sure the resource is freed, we must _catch_ any errors that might cause the procedure to return before the freeing of the resource. The solution looks like: proc doSomething {} { set resource [allocate] catch { # Arbitrarily long script of operations } result options deallocate $resource return -options $options $result } With that structure, we are confident the resource is always freed, but any error or exception will be presented to the caller exactly as if it had never been caught in the first place. Here are two examples of how to use the new features in a control structure proc. The essence of a control structure command is its ability to evaluate a script in the caller's context, preserving the illusion that no additional stack frame was ever used. So, a proc replacement for _eval_ illustrates the technique. The first approach assumes one knows the internal details of how the _uplevel_ command adds to the stack trace. This is straightforward, but will require a rewrite if _uplevel_ ever changes how it manipulates the stack trace. proc myEval script { if {[catch {uplevel 1 $script} result options] == 1} { set stack [dict get $options -errorinfo] regsub {\s+invoked from within\s+"uplevel 1 \$script"$} $stack {} stack regsub {\("uplevel" body line (\d+)\)$} $stack [subst -nobackslashes \ {("[lindex [info level 0] 0]" body line \1)}] stack dict set options -errorinfo $stack } dict incr options -level return -options $options $result } A second, more robust solution is possible, but requires a bit more context gymnastics. namespace eval control { proc eval script { variable result variable options set code [uplevel 1 \ [list ::catch $script [namespace which -variable result] \ [namespace which -variable options]]] if {$code == 1} { set line [dict get $options -errorline] dict append options -errorinfo \ "\n (\"[lindex [info level 0] 0]\" body line $line)" } dict incr options -level return -options $options $result } } Note that in the second solution we did not have to strip away the contributions of _uplevel_ to the stack trace, because we captured the stack trace before _uplevel_ added anything. Then we could add our own information \(drawing in part on the new "-errorline" value available to us now at the script level\). We confirm that either approach solves the original problem: % proc a {} {eval {return -code error}} % proc b {} {myEval {return -code error}} % proc c {} {control::eval {return -code error}} % catch a 1 % catch b 1 % catch c 1 Finally, the new features make possible a utility command that can be of use to people making simple control structure commands, or doing simple wrapping, where there is no need to augment the stack trace, or to treat any return codes in a special way: namespace eval control { proc ascaller script { if {[info level] < 2} { return -code error \ "[lindex [info level 0] 0] called outside a proc" } variable result variable options set code [uplevel 2 \ [list ::catch $script [namespace which -variable result] \ [namespace which -variable options]]] if {$code == 0} { return $result } dict incr options -level 2 return -options $options $result } } Within a proc, _ascaller $script_ will take care of all aspects of evaluating _$script_ in the caller context, and exiting as appropriate for all non-TCL\_OK return codes. # Extensibility The _return -code_ command has always accepted any integer value as a valid argument, allowing package and application authors to define their own new return codes as needed by their own control structure commands. Now that _return_ will accept any _option_ argument, and _catch_ can capture all _option value_ argument pairs passed to the caught _return_ command, package and application authors now have the ability to augment their custom return codes with additional data. Some prefix convention should be established to avoid key name conflicts in the return options dictionary. # Potential Concerns Reviewers of drafts of this TIP wondered whether the new "-level" option to _return_ raised the possibility of trouble with an attempt to return more levels than beyond the top of the call stack. It should be understood that _return -level N_ does not take any shortcut past the intervening levels. Each level of the call stack gets a TCL\_RETURN return code, and a "-level" value, dropping by one each step up the stack. Any level in the stack might choose to _catch_ the TCL\_RETURN and treat it as it wishes. This is exactly the way the existing _return -code return_ is handled. Normally, it would cause a normal return to the caller's caller, but if the caller chooses to 'catch' it, then the caller has control. At the toplevel we run out of callers. Then the question becomes how is a TCL\_RETURN code at toplevel handled? % return -level 0 ;# same as a TCL_OK at toplevel % return -level 1 ;# same as [return] % return -level 2 ;# same as [return -code return] command returned bad code: 2 From the C level, _Tcl\_AllowExceptions\(\)_ can be used to modify this toplevel behavior. The following proc will produce the same results as above, but from any level in the call stack \(absent an intervening _catch_\): % proc escape level { set x [info level] incr x $level return -level $x } % escape 0 % escape 1 % escape 2 command returned bad code: 2 Another concern was whether this proposal gave slave interpreters any new powers over their masters. The return code from evaluation of an untrusted script in a slave interpreter should always be wrapped in a _catch_ already, lest a TCL\_ERROR in the script blow the stack. Given that, the only thing this proposal does is give the _catch_ command more information to use to decide how to handle the misbehaving script. # Compatibility It is the author's belief that this proposal is completely compatible with prior Tcl 8.X releases. Any error-free script that ran before, should continue to run with the same results. At the C level, only internal changes are made, and no new interfaces are defined. Any extension or embedding C program that sticks to the public stubs interface should see no visible change. # Prototype This proposal is implemented by Tcl Patch 531640 at SourceForge. The prototype covers all described functionality, but might be further improved with more substantial bytecompiling of [return]. # Future considerations The main reason the global variables _::errorInfo_ and _::errorCode_ exist is to give the script level access to stack and error code information following the _catch_ of a script that raises an error. After this proposal, the _catch_ command itself provides access to that information, so the global variables are not required. One can imagine deprecating them, asking users of Tcl 8.5 to stop writing code that accesses them. They could still have apparent existence, to satisfy the needs of scripts written for earlier Tcl 8.X releases, by means of read traces. In time, Tcl 9 could either continue the read trace scheme, or not provide these global variables at all. One part of Tcl itself that currently makes use of the _::errorCode_ and _::errorInfo_ variables is the _bgerror_ command. Currently, _bgerror_ accepts exactly one argument, the error message. To make use of stack or error code information, _bgerror_ must retrieve them from the global variables. The proper values of these global variables are re-set by _Tcl\_BackgroundError\(\)_ prior to evaluation of _bgerror_. As an alternative, _Tcl\_BackgroundError\(\)_ could first attempt to call _bgerror_ with _two_ arguments, first the message, then a dictionary of options. If that call returned TCL\_ERROR, then a second attempt could be made with a single message argument. In that way, cleaner _bgerror_ commands that get all data from arguments could be supported, while still keeping support for those _bgerror_ commands that were defined for single argument use. It has been noted several times that the processing of the value of _::errorInfo_ is rather difficult because it is an arbitrary string with no documented structure. A different, more structured way of representing stack trace information would be an improvement. This proposal does not propose an alternative, but because it offers an extensible dictionary for storing arbitrary return options data, it does provide an infrastructure where such approaches might be tried out. # Acknowledgments This proposal is a synthesis of ideas from many sources. As best I can recall, major contributions came from Joe English, Andreas Leitgeb, Reinhard Max, and Kevin Kenny. If you like the idea, give them some credit; it you don't, blame me for combining the ideas badly. # See also Documentation for tcllib's control package: <http://tcllib.sf.net/doc/control.html> # Copyright This document has been placed in the public domain. |
Name change from tip/91.tip to tip/91.md.
|
| < | | | | | | < | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 91: Backward Compatibility for Channel Types with 32-bit SeekProcs State: Final Type: Project Tcl-Version: 8.4 Vote: Done Post-History: Author: Donal K. Fellows <[email protected]> Created: 03-May-2002 ----- # Abstract [[72]](72.md) broke backward-compatibility for channels that supported the [seek] command, and this TIP adds the ability for old-style channels to work with the underlying 64-bit architecture. # Rationale Although the ability to work with large files \(as added by [[72]](72.md)\) is crucially useful in many situations, it has introduced a few problems, one of which being that it broke backward compatibility for channel types \(see <http://sourceforge.net/tracker/?func=detail&atid=410295&aid=551677&group\_id=34191> for details.\) Following discussion with the people concerned, I believe it is possible to modify the channel type structure so that old-style channels - i.e. those compiled against Tcl 8.3 - can still be supported \(though with a limited range of operation.\) # Proposed Change The _Tcl\_ChannelType_ structure will have an extra field appended of type _Tcl\_DriverWideSeekProc_ called _wideSeekProc_, which shall be guaranteed to be present \(though possibly NULL\) whenever the version of the _Tcl\_ChannelType_ structure is at least _TCL\_CHANNEL\_VERSION\_3_. The type _Tcl\_DriverSeekProc_ shall be reverted to its pre-[[72]](72.md) version, with the current type of _Tcl\_DriverSeekProc_ being transferred to the type _Tcl\_DriverWideSeekProc_. In order to facilitate stacked channels, an additional requirement shall be imposed that if a channel driver implements a _wideSeekProc_, then it shall also implement a _seekProc_, so allowing stacked channels to work entirely in one domain or the other \(well, in simple cases at least.\) Semantically, the core will handle seeks by preferring to use a _wideSeekProc_ if present, and using the _seekProc_ otherwise. Considering just the case where the _seekProc_ is used, if the offset argument exceeds that which is representable in a _long_, _Tcl\_Seek_ will fail, simulating a system error of EOVERFLOW. The only Tcl core channel which will need modification is the _file_ channel; this will be adapted to generate an error of EOVERFLOW when the resulting offset in a file would otherwise exceed that which can be expressed in a _long_ \(which has the downside of making the seek operation no longer atomic when using the old interface, since the file offset will need to be restored to its old position in such cases.\) On 64-bit platforms, both _seekProc_ and _wideSeekProc_ will be the same function. # Rejected Alternatives I considered overloading the _seekProc_ field to have different types depending on the value of the _version_ field, but that's remarkably ugly and forces people to adapt rapidly at a source level. I don't know about everyone else, but I don't use a lot of programs at the moment that actually need access to files larger than 2GB. I also considered allowing code to only implement the _wideSeekProc_ but it was easier to code the way I ended up doing it and I don't think there are that many people writing channel drivers that support seeking anway. # Copyright This document has been placed in the public domain. |
Name change from tip/92.tip to tip/92.md.
|
| < | < | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | < > | | | | | | < > | | | | < > | | | | < > | < > | | | | < > | | | < > | | | < > | | | < | > | | | | | | | | | | | | | | > | 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 | # TIP 92: Move Package Load Decisions to Application Developer Author: Clif Flynt <[email protected]> State: Withdrawn Type: Project Vote: Pending Created: 13-May-2002 Post-History: Tcl-Version: 8.4 Keywords: package require, namespace, pkg_mkIndex ----- # Abstract This TIP makes the loading of packages far more flexible, so as to better support their use by application authors in situations above and beyond those foreseen by the developer of the package. # Overview I believe that we've been misdirecting our efforts in solutions to the Package issue. * The modifications to _pkg\_mkIndex_ give the library author \(or package builder\) the ability to define when a package will be loaded \(immediate or deferred\), which restricts an application developer to the decisions made by the library author. * If a package is built to be loaded immediately, it is loaded into the top-level namespace. This breaks previous tricks to force a package to load inside an existing namespace. These techniques limit the application writer to the behavior \(and uses\) envisioned by the package author and is counter to the concept that application developer best understands how they need a tool to perform for their application. The Tcl community, in particular, has grown largely because the tools have had applications far beyond those imagined by their initial developers. Moving the decisions about when and how to load a package from _pkg\_mkIndex_ to the _package require_ command allows the application writer the freedom to find new styles of use that the package author may not have conceived. Being able to force an immediate load into the current namespace rather than always loading packages into the global scope provides support for lightweight object style data structures without the need for extensions like Incr Tcl, OOTcl, etc. Loading a package/namespace into the current namespace provides mechanisms for lightweight inheritance, and since namespaces can contain both code and data, loading a namespace multiple times \(in separate namespaces\) is a lightweight aggregation model. I do not propose that this power removes the need for full object oriented programming models within the Tcl community. However, I believe that putting the power to develop these lightweight models into the application developer provides the developer with a more versatile tool kit than they currently have. \(One that I've been using for several years, with workarounds.\) This proposal is to add new flags to the package require command, allowing an application developer to determine when and how to load a package. -current: Load the package into the current namespace rather than the global space. Implies immediate. -multiple: Allow loading multiple copies of this package, for use with _-current_ when the application programmer wishes to create multiple nested copies of a package. -immediate: Load immediately, rather than defer loading the package until needed. This is the default behavior with Tcl 8.3 and later. -defer: Load package when required. The default with Tcl 8.2 and earlier, or when _pkg\_mkIndex -lazy_ used with Tcl 8.3. -exact: No change to this option. Requires an exact Major/Minor revision match to be an acceptable package. # Script Example The code below implements a simple stack object that can be merged into other namespaces to create objects that contain individual stacks. package provide stack 1.0 namespace eval stack { namespace export push pop peek size variable stack "" proc push {val} { variable stack; lappend stack $val } proc pop {} { variable stack; set rtn [lindex $stack end] set stack [lrange $stack 0 end-1] return $rtn } proc peek {{pos end}} { variable stack; return [lindex $stack $pos] } proc size {} { variable stack; return [llength $stack] } } With this data structure available, the guts of a Tower of Hanoi puzzle becomes simple: namespace eval left { package require -current -multiple stack 1.0 namespace import [namespace current]::stack::* } namespace eval center { package require -current -multiple stack 1.0 namespace import [namespace current]::stack::* } namespace eval right { package require -current -multiple stack 1.0 namespace import [namespace current]::stack::* } proc move {from to} { ${to}::push [${from}::pop] } This creates 3 'objects' each of which contains a private stack with the stack methods. # Reference Implementation A reference implementation of the _-current_ and _-multiple_ flags has been created for Tcl 8.4a4 and is available at <http://noucorp.com/PkgPatch8.4.zip> The implementation required these modifications to _generic/tclPkg.c_: * _Tcl\_PackageObjCmd_ needs to be able to parse the new options and set the bitmapped flag. * _Tcl\_PkgRequireEx_ is modified to accept a bitmapped flag instead of the _exact_ option. * The 0x0001 bitmap position is used to map for _exact_ preserving the existing behavior of the _Tcl\_PackageObjCmd_ and _Tcl\_PkgRequireEx_ functions. * These bitmapped flags are defined exact, current, and multiple: #define PKG_EXACT 0x01 /* Use the exact version - as used for exact */ #define PKG_CURRENT 0x02 /* Load into current namespace, not GLOBAL */ #define PKG_MULTIPLE 0x04 /* Allow loading multiple copies of a package */ * _Tcl\_PkgRequireEx_ is modified to process the MULTIPLE and CURRENT flags. * The Tcl tests have been reworked to understand the new error returns, etc. Running "make tests" will accept the new code. Minimal testing has been done using pure Tcl packages. |
Name change from tip/93.tip to tip/93.md.
|
| < | < | | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | < > | | | | | | | | | | | | | | < | > | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 93: Get/Delete Enhancement for the Tk Text Widget Author: Craig Votava <[email protected]> Author: Donal K. Fellows <[email protected]> Author: Jeff Hobbs <[email protected]> State: Final Type: Project Vote: Done Created: 28-Dec-2001 Post-History: Tcl-Version: 8.4 ----- # Abstract The Tk Text widget provides text tags, which are a very powerful thing. However, the current implementation does not provide an efficient way for a Tk Text widget programmer to extract \(get\) all of the actual text that has a given text tag. This TIP proposes to enhance the Tk Text widget to provide this functionality. # Rationale While writing applications using the Tk Text widget, I find myself wanting to extract all of the text that has a given text tag. Although this is possible with the existing functionality of the Tk Text widget, it can become extremely inefficient, depending on your application. Consider the example where we load a text widget with say, the contents of a scene from a play, and we tag all of the spoken passages with the name of the character that utters them. How can we provide an efficient way to allow an end user to print out all the spoken text for a single given character? My initial impulse was to design something like this \(please excuse the use of Perl-Tk syntax, that's what I'm most comfortable with\): $txt->tagGet($tag); The problem with this design is what should this return? A string? An list? If a list, should it be a list of each tagged character? A list of strings containing all contiguous characters? In addition, Steve Lidie points out that the corresponding tagDelete\(\) command would also have to be modified to mimic this change as well. This line of thought got icky pretty fast. My second impulse was to try to induce this functionality with as much existing stuff as possible. The _tagRanges_ command returns a list of index pairs for all contiguous characters with a given tag. The thought here was to combine that command with the _get_ command to get all the text with a given tag: $txt->get( $txt->tagRanges($tag) ); This design seems to fit in well with much of the existing functionality of the text widget. The main problem here is that the existing _get_ command only allows for either one or two arguments, and returns a single string. For this design to be implemented, the get interface would need to be enhanced. This is the design I chose to implement as a reference \(prototype\) implementation. I believe that the functionality should be provided in the Tk Text widget, and believe that this prototype solution could be turned into a production solution. However those decisions I happily leave up to the Tk developers who are more knowledgeable about the Tk Text implementation than myself. An additional concern here involves the corresponding text delete command. Should the delete command also be modified in a similar way so that it has this same functionality too? It seems like it should. # Specification This specification will only describe how the reference implementation was produced. If it is decided that an alternate design is needed for the final production solution, this specification can be scrapped. The goal of this design is to enhance the Tk Text _get_ command from accepting only one or two arguments, to accepting any number of 1 \(\+NULL\) or 2 arguments sets. The Tcl-Tk manual page description would change from this: $t get i1 ?i2? to something like this: $t get i1 ?i2? ?(i3 ?i4? ...)? By providing this enhancement, we give the programmer with the ability to efficiently _get_ all of the text that is tagged with a given tag. The programmer would do this by using a compound statement utilizing the existing _tag ranges_ command along with the enhanced _get_ command, as follows \(the examples are using the Perl-Tk syntax\): $txt->get( $txt->tagRanges($tag) ); In addition, the enhancement will preserve compatibility with all of the existing Tk _get_ commands currently in use. Currently, the _get_ command simply returns a single string containing all of the characters specified by the first and \(optionally\) the second argument\(s\). The enhanced _get_ command will preserve this existing functionality: my $chr = $text->get('1.0'); > This command functions exactly the same as the original _get_ command. It will return a string containing the first character from the first line. my $str = $text->get('1.0', '1.0 lineend'); > This command functions exactly the same as the original _get_ command. It will return a string containing all of the characters on the first line. However, if the programmer provides more than one or two argument\(s\), the enhanced _get_ command will return a list of strings, just as if the original _get_ command was called multiple times and the results were loaded into a programmer-defined list: my @lines = $text->get('1.0', '1.0 lineend', '2.0'); > This command returns a list whose first element \(_$lines[[0]](0.md)_\) is a string containing all of the characters from the first line, and the second element \(_$lines[[1]](1.md)_\) is a string containing just the first character of the second line. my @lines = $text->get('1.0', '', '2.0', '2.0 lineend'); > This command returns a list whose first element \(_$lines[[0]](0.md)_\) is a string containing just the first character from the first line, and the second element \(_$lines[[1]](1.md)_\) is a string containing all of the characters on the second line. my @lines = $text->get('1.0', '1.0 lineend', '2.0', '2.0 lineend'); > This command returns a list whose first element \(_$lines[[0]](0.md)_\) is a string containing the all of the characters from the first line, and the second element \(_$lines[[1]](1.md)_\) is a string containing all of the characters from the second line. All of this paves the way for the programmer to use the compound command: my @lines = $txt->get( $txt->tagRanges($tag) ); > This command returns a list whose elements are strings of all the contiguous characters tagged with a given tag. # Example The following Perl-Tk code illustrates how the enhanced _get_ command could be used with the existing _tag ranges_ command to efficiently extract all of the text that is tagged with a given tag. #! /usr/local/bin/perl -w require 5.005; use strict; use English; use Tk; # Create main window with button and text widget in it... my $top = MainWindow->new; my $btn = $top->Button(-text=>'print odd lines')->pack; my $txt = $top->Scrolled('Text', -relief=>'sunken', -borderwidth=>'2', -setgrid=>'true', -height=>'30', -scrollbars=>'e'); $txt->pack(-expand=>'yes', -fill=>'both'); $btn->configure(-command=>sub{&GetText($txt)} ); # Populate text widget with lines tagged odd and even... my $lno; my $oddeven; foreach $lno (1..20) { if($lno % 2) { $oddeven = "odd" } else { $oddeven = "even" }; $lno = "Line $lno ($oddeven)\n"; $txt->insert ('end', $lno, $oddeven); } # Do the main processing loop... MainLoop(); sub GetText { my $txtobj = shift; $txtobj->tag('configure', 'odd', -background=>'lightblue'); $txtobj->tag('configure', 'even', -background=>'lightgreen'); # This is the goal of all the work... my @lines = $txtobj->get($txtobj->tagRanges('odd')); print STDERR join("", @lines); } # Reference Implementation The patch for this reference implementation has been posted to the ptk mailing list. An archived version is available at: <http://faqchest.dynhost.com/prgm/ptk-l/ptk-01/ptk-0112/ptk-011201/ptk01122716\_24437.html> I have written and run a single benchmark test \(in Perl-Tk\) to compare this reference implementation against a traditional method of extracting all text with a specific tag. The results of this specific benchmark test \(tagging odd lines _odd_ and even lines _even_ in a text window with 2000 entries\), run on my computer are as follows: Reference Implementation 0.105 CPU Seconds (average over 10 runs) Traditional Method 0.443 CPU Seconds (average over 10 runs) I believe that both the CPU the efficiency, and the coding efficiency that this reference implementation provides, merit the change to the Tk Widget. In addition to the _get_ enhancement, the symmetrical changes would be make to the _delete_ subcommand. _The patch has received little testing so far, so any testing is encouraged._ # Notes on Equivalent Behaviour in Tcl/Tk Tcl has less of a need for this than Perl because it has a striding [foreach] allowing the list of indices returned by the [$t tag ranges] subcommand to be traversed in a straight-forward fashion, but this sort of functionality is still useful. The motivating examples above become \(in order\): set lines [$t get 1.0 "1.0 lineend" 2.0] set lines [$t get 1.0 {} 2.0 "2.0 lineend"] set lines [$t get 1.0 "1.0 lineend" 2.0 "2.0 lineend"] set lines [eval $t get [$t tag ranges]] # Copyright This document has been placed in the public domain. |
Name change from tip/94.tip to tip/94.md.
|
| < | < | | | | | | | > | | | | | | | | | | | | | | > | 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 | # TIP 94: Add Listbox -activestyle Option Author: Jeff Hobbs <[email protected]> State: Final Type: Project Created: 29-May-2002 Tcl-Version: 8.4 Vote: Done Post-History: ----- # Abstract This TIP proposes to add a [-activestyle] option to the [listbox] widget that would control what style the active element has when the widget has focus \(currently hard-coded to be underlined\). # Rationale Tk has always had an underline on the active item in listboxes, which is shown when the listbox has focus. However this in incompatible with the style of listboxes on Windows, especially as used in drop-down boxes. They instead have a thin dotted line to indicate the active item. In order to improve native look and feel, we would allow the user to request the style which indicates the active item. # Specification $listbox configure -activestyle none|underline|dotbox The default would be underline, which stays consistent with the current behavior. _dotbox_ is the Windows style, which is essentially the dotted focus ring that any item with focus receives. While Windows does have a special API \(_DrawFocusRect_\) to draw this, it should be possible with the features of the dash patch to emulate on Unix. It may not be possible to draw a dotbox easily on MacOS, in which case the option will be allowed, but nothing would be drawn \(rather than dropping back to underline\). # Reference Implementation This implementation is simple and would only extend one check in _DisplayListbox_ for whether the underline should be drawn. File: _tcl/generix/tkListbox.c_ Function: _DisplayListbox_ # Copyright This document has been placed in the public domain. |
Name change from tip/95.tip to tip/95.md.
|
| < | < | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 95: Add [wm attributes] Command Author: Jeff Hobbs <[email protected]> State: Final Type: Project Vote: Done Created: 29-May-2002 Post-History: Tcl-Version: 8.4 ----- # Abstract This TIP proposes adding a [wm attributes] command in order to control platform-specific aspects of a toplevel. In addition, it proposes making [wm] a _Tcl\_Obj_-based command and centralizing the common functionality. # Rationale While Tk has been proven useful over time as a cross-platform toolkit, it has some serious drawbacks in acceptance due to small, but important, lacking functionality in the handling of toplevel windows on certain platforms. Having a toplevel stay on top on Windows is a prime example of a commonly requested feature for which there is no core support. Mac/Tk has long had a special unknown command to support special styles needed for proper "look and feel" there. I hereby propose a [wm attributes] command \(like the [file attributes] command\) to providing platform-specific functionality for toplevel windows. # Specification wm attributes $toplevel ... [[WINDOWS]] ?-disabled ?bool?? ?-toolwindow ?bool?? ?-topmost ?bool?? ?-minimizebox ?bool?? ?-maximizebox ?bool?? ?-sysmenu ?bool?? [[MAC]] ?-style ?alert|moveablealert|modal|moveablemodal| floating|document ...?? [[UNIX]] <empty at this time> Because Tk started off on Unix, most potential attributes are already in the wm command, whether they really make sense across platforms or not \(some equivalent has been emulated in most cases\). If someone feels that there are some X window attributes that Tk does not support, this would be the place to put them. On Windows, most of the attribute settings can be combined \(they are OR-ed bits of special style fields on a toplevel\), which is why they are set or retrieved as booleans. The names reflect their Win32 API bits. For Windows and the Mac, the naming of attributes and/or styles mirrors the native API as closely as possible, as we are exposing native platform functionality in this command. More specifics about Windows styles can be seen here: > <http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnwui/html/msdn\_styles32.asp> For Macs, styles are mutually exclusive, so you set one of a list of available styles. MacOS has nine standard window types and eight standard floating window types. More information can be seen here: > <http://developer.apple.com/techpubs/quicktime/qtdevdocs/INMAC/MACWIN/imWindowMgrRef.3.htm> # Reference Implementation Mac/Tk has a reference implementation already that would just adapt the existing _unsupported1_ code to _wm attributes_. There are two variant patches for the Windows work in Tk patch 553926 at SF. File: _tk/mac/tkMacWm.c_ File: _tk/win/tkWinWm.c_ File: _tk/unix/tkUnixWm.c_ Function: _Tk\_WmCmd_ # Comments Several names have been used for a command with similar functionality. Mac/Tk uses the _style_ command, as does Tk Patch 553926. This is only for platform-specific configuration of toplevel windows, and it not necessarily limited to style. I considered _wm configure_, but I chose _wm attributes_ because that worked just as well and had the equivalent of _file attributes_ to support the naming. Windows toplevels could have more special styles like _-transparent_, Windows scrollbars on the toplevel and a few other window styles that the Win32 API supports. Only the styles that have had user requests are supported at this time. We may want to add _-caption_ and _-dialogmodal_ support if these seem useful. It was recommended that commonality be reached where possible, but this tip addresses most specifically what isn't common across the minute aspects of toplevel window handing on different platforms. For examples, for Windows to allow TOPMOST, it keeps a special list of the topmost windows. This manager-level support is necessary to avoid contention amongst topmost windows. Macintosh has many special dialog and window styles to represent both changing UI design over time, as well as the latest in UI design that can be reached standard for Mac toplevels but not Unix or Windows ones. It may be that certain functionality will become cross-platform as native APIs develop, but this is meant to allow access to key native look and feel features that Tk lacks for serious developers now. # Copyright This document has been placed in the public domain. |
Name change from tip/96.tip to tip/96.md.
|
| < | < | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 96: Add [tk caret] Command and Tk_SetCaretPos API Author: Jeff Hobbs <[email protected]> State: Final Type: Project Created: 29-May-2002 Tcl-Version: 8.4 Vote: Done Post-History: ----- # Abstract This TIP proposes to add a [tk caret] command and [Tk_SetCaretPos] C API to manage _carets_ in Tk. _caret_ is the term for where text of graphics will be inserted. It is necessary for correct accessibility functionality \(to know where to shift focus\), and for location the IME or XIM input box to handle complex character input \(e.g. Asian character sets\). # Rationale Tk has up until now not managed the caret within its windows. This has led to it being not Windows Accessibility certifiable. On Windows, this also cause the IME window to show in the top-left corner of the window \(somewhat OK for entries, bad for text widgets\). On X, this meant that Tk had to use the root-window style XIM input, which is a poor second to over-the-spot XIM input. Managing the caret corrects these problems. Exposing the functionality at the Tcl level allows extension writers to use the functionality without having to make Tk version API checks. A simple catch {tk caret $w -x $x -y $y} will suffice to work across versions. # Specification tk caret window ?-x xPos? ?-y yPos? ?-height height? void Tk_SetCaretPos (Tk_Window tkwin, int x, int y, int height) _-height_ specifies the height of the input line and is important because Windows and X interpret the x,y coordinates differently \(top-left and bottom-left respectively\), so it must be adjusted by height for X. If no height is specified, the height of the window passed in will be used. I chose to use the _-option value_ format because it allows for future extensibility. There are APIs to control the font and other aspects of the IME/XIM input window that appears, but management of these is not covered in this tip. # Reference Implementation The Tk\_SetCaretPos implementation is currently in the core. It needs to be modified to move the caret information to be per display, instead of per process. File: _tk/mac/tkMacXStubs.c_ File: _tk/win/tkWinX.c_ File: _tk/unix/tkUnixKey.c_ Function: _Tk\_SetCaretPos_ # Comments The current implementation at the C level was implemented with the assistance of Keiichi Takahashi \(BitWalk\), Koiichi Yamamoto, Moo Kim \(NCR\), and Mike Fabian \(SuSE\). It has been tested on Windows 98/2000/XP and SuSE 7.3 using kinput/canna2. # Copyright This document has been placed in the public domain. |
Name change from tip/97.tip to tip/97.md.
|
| < | < | | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 97: Moving Vertices of Canvas Items Author: Agnar Renolen <[email protected]> Author: Donal K. Fellows <[email protected]> State: Final Type: Project Tcl-Version: 8.6 Vote: Done Created: 07-Jun-2002 Post-History: Keywords: Tk ----- # Abstract This TIP proposes a canvas subcommand \(or possibly two\) that allows for replacing characters in text objects and to move individual vertices of line and polygon items. # Rationale Interactive graphics programs often allow users to modify shapes of objects by selecting and dragging the vertices. Moving one vertex of a canvas item in the current version of Tk, \(at least as far as I can find out from the documentation\), can only be done by first removing the coordinate by **dchars** and then insert the new one by **insert**, or for geometric items like lines and polygons using the **coords** command to obtain and reset the coordinates, after having modified the coordinate list by **lreplace**. The most important issue here, I think, is performance. I believe that the current way of moving a vertex can be slow in some scenarios. The **rchars** canvas subcommand is proposed merely to conform with the **dchars** and **insert** commands, which both operate on lines, polygons and text items, hence **rchars** should do that as well. # Specification Two canvas widget subcommands are proposed: **imove** and **rchars**. The following subcommand is proposed to move a vertex of any canvas item: > _canvas_ **imove** _tagOrID index x y_ This subcommand will move the _index_th coordinate of the items identified by _tagOrID_ to the new position given by _x_ and _y_. The _index_ value will be processed according to normal canvas index rules \(see the INDICES section of the **canvas** manual\). The subcommand will only work for line and polygon items \(or any third party items that set the TK\_MOVABLE\_POINTS flag\). The following command provides a similar functionality, but conforms to the model of the current **insert** and **dchars** subcommands. > _canvas_ **rchars** _tagOrID first last string_ This command will: for text items: replace the characters in the range _first_ and _last_ \(inclusive\) with the characters in _string_. for line and polygon items: replace the coordinates in the range _first_ and _last_ \(inclusive\) with the coordinate list specified in _string_ \(subject to the requirement that the coordinate list is an even number of floating point numbers\). In both cases, _first_ and _last_ will be processed according to the rules in the INDICES section of the **canvas** manual page. At the C level, the only change is the addition of a new flag, **TK\_MOVABLE\_POINTS**. If this flag is set in the _alwaysRedraw_ field of the item type structure, it implies that the item supplies non-NULL _dcharsProc_, _indexProc_ and _insertProc_ fields, and gives them semantics equivalent to the line and polygon items \(i.e. that the methods will work with the coordinate list\). Note that text items, despite having all the required methods, do not set the flag because those methods work with character indices. ## Notes The **imove** subcommand is not strictly necessary as the **rchars** subcommand can be used to obtain the same result. However, I believe that a separate **imove** subcommand will be easier to understand for users than the **rchars** subcommand, though the latter is still necessary as it allows for more complex processing such as insertion or deletion of points. # Reference Implementation See Patch 2157629<https://sourceforge.net/support/tracker.php?aid=2157629> . # Copyright This document has been placed in the public domain. |
Name change from tip/98.tip to tip/98.md.
|
| < | | | < | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 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 | # TIP 98: Adding Transparency Compositing Rules to Photo Images Author: Donal K. Fellows <[email protected]> Created: 09-Jun-2001 Type: Project State: Final Vote: Done Tcl-Version: 8.4 Post-History: ----- # Abstract This TIP adds compositing rules to Tk's photo images to give programmers better control over what happens when two transparent images are combined. This TIP also allows for several frames of an animated GIF file to be correctly displayed in an image even when the transparent area is not constant. # Rationale This is a TIP that is inspired by the tkchat application in Tcllib, and in particular by the image used to represent the LOL smiley. The problem with this image is that its transparent area changes over time, and this is caused by the fact that _Tk\_PhotoPutBlock\(\)_ only allows one way of compositing a block with an image; it behaves as if the data being added was on a sheet of cel \(the material used to make hand-drawn animated cartoons\) allowing for sophisticated layering effects. Unfortunately, for many applications \(and animated GIF images are definitely among these\) this sophistication works against us. In a GIF image, transparency is treated not as extra information that is added to each pixel's colour, but rather as a special colour; a pixel cannot be, for example, red and transparent at the same time. Support for this requires a different \(and indeed simpler\) kind of compositing rule. And of course, once you have such a facility in the underlying C code, it should be exposed to scripts. There are other kinds of compositing rule \(for example, acting like the added block is placed under the image, and many others\) but this TIP does not propose adding anything other than a way to chose between the current behaviour and the behaviour required for supporting GIF animation, in the belief that those two compositing rules are the ones most useful to programmers, and that once the general facility is there, the other rules will be relatively easy to add in the future. # Specification This TIP adds a _compositingRule_ argument to _Tk\_PhotoPutBlock_ \(and _Tk\_PhotoPutZoomedBlock_\) to allow selection between the current behaviour \(overlaying\) and the other one I wish to support \(setting/overriding.\) The permitted values of this argument will be _TK\_PHOTO\_COMPOSITE\_OVERLAY_ \(the currently implemented behaviour\) and _TK\_PHOTO\_COMPOSITE\_SET_ \(the behaviour required to support GIF file animation.\) At the Tcl level, when copying from one image to another \(the other photo image subcommands do not currently support transparency at all\) the _photo get_ will take an extra option _-compositingrule_ to allow selection of the compositing rule. The permitted values of this option will be _overlay_ and _set_ by analogy with the values described above. # Implementation Notes Proposed implementation patch: <https://sourceforge.net/tracker/index.php?func=detail&aid=566765&group\_id=12997&atid=312997> The proposed implementation of this TIP naturally includes backward-compatibility functions that allow pre-compiled extensions to continue to operate without recompilation \(provided they use Stubs for linking.\) Furthermore, extension authors can also define the symbol _USE\_COMPOSITELESS\_PHOTO\_PUT\_BLOCK_ when compiling and have source-level compatibility with the old functions. The proposed implementation also creates _TkSubtractRegion_ as a new internal function; it is the analogue of _XSubtractRegion_ as _TkIntersectRegion_ is the analogue of _XIntersectRegion_. It might be useful to other parts of the core that manipulate regions. Both the PPM and GIF file readers use the _set_ compositing rule, PPM because the format does not support transparency \(and _set_ should at least theoretically be faster\) and GIF because it is required semantically. Other image formats are not required to do this, of course. The _$img put $data_ photo image subcommand uses _set_ compositing because it does not support transparency. # Copyright This document is placed in the public domain. |
Name change from tip/99.tip to tip/99.md.
|
| < | < | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | < > | < > | > | 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 | # TIP 99: Add 'file link' to Tcl Author: Vince Darley <[email protected]> State: Final Type: Project Vote: Done Created: 11-Jun-2002 Post-History: Tcl-Version: 8.4 ----- # Abstract Tcl can read links, but cannot create them. This TIP proposes adding a _file link_ subcommand to allow cross-platform creation of links. # Proposal Add a new subcommand with the following syntax: file link ?-linktype? linkName ?target? If only one argument is given, that argument is assumed to be _linkName_, and this command returns the value of the link given by _linkName_ \(i.e. the name of the file it points to\). If _linkName_ isn't a link or its value cannot be read \(as, for example, seems to be the case with hard links, which look just like ordinary files\), then an error is returned. If 2 arguments are given, then these are assumed to be _linkName_ and _target_. If _linkName_ already exists, or if _target_ doesn't exist, an error will be returned. Otherwise, Tcl creates a new link called _linkName_ which points to the existing filesystem object at _target_, where the type of the link is platform-specific \(on Unix a symbolic link will be the default\). This is useful for the case where the user wishes to create a link in a cross-platform way, and doesn't care what type of link is created. If the user wishes to make a link of a _specific type only_, \(and signal an error if for some reason that is not possible\), then the optional _linktype_ argument should be given. Accepted values for linktype are _-symbolic_ and _-hard_. When creating links on filesystems that either do not support any links, or do not support the specific type requested, an error message will be returned \(in particular Windows 95, 98 and ME do not support any symbolic links at present, but Unix, MacOS and Windows NT/2000/XP \(on NTFS drives\) do\). The TIP proposes implementing: Unix,MacOSX Win-NTFS MacOS symbolic: yes directories-only yes hard: files-only files-only no This also leaves the avenue open, in the future, for the addition of other link types \(e.g. Windows shortcuts\) through additions to list of acceptable _linktype_s. This TIP only proposes adding the above options. This means that a general _[file link $linkname $target]_ should always succeed on the above platforms \(for both files and directories\), but uses of _-hard_ or _-symbolic_ could fail, depending on the current platform, and the type of the path. # Rationale There are many requests on comp.lang.tcl for this functionality \(see <http://groups.google.com/groups?dq=&hl=en&lr=&ie=UTF8&oe=UTF8&threadm=4dd3bea3.0206100250.95eeb4e%40posting.google.com&rnum=1&prev=/&frame=on> for a recent thread\), and if Tcl can read links \(_file readlink_, _file lstat_\), it really ought to be able to write them. Discussion has shown that both symbolic and hard links are desirable, and that for cross-platform use a general-purpose _file link_ which creates _something_ is useful. Some users would prefer hard links to be the default, but on balance most people commenting seemed to prefer symbolic links as default. This has the added benefit that symbolic links will then be the default on MacOS, Unix and Windows for everything, _except_ files on WinTcl \(where hard-links are required\). # Alternatives There is no cross-platform alternative available. TclX provides a _link_ command for Unix only, and Unix platforms can also use _exec ln ?-s?_ command to achieve the same effect. # Reference Implementation Tcl contains a _testfilelink_ command in _generic/tclTest.c_, which is a partial implementation used by the test suite. For a full implementation of this TIP, including the _-linktype_ switch, see: _ <http://sourceforge.net/tracker/index.php?func=detail&aid=562970&group\_id=10894&atid=310894> _ which includes extensive docs and tests. # Copyright This document has been placed in the public domain. |